切勿使用:指向局部变量的指针作为函数的返回指针!

今天码代码的时候,出现了一个诡异的问题:

首先:函数 pkt_analyzer 返回了一个
PktUnit类型的指针。我先把端点跑到puu赋值后的下一句,查看puu里面的内容,发现是正确的: payload_len = 7,pkt_len =
35

接着我再向下跑一步,发现puu内容就不对了: payload_len = 1514280713 ;pkt_len = 17 整个就不对了……

找了一个多小时,没发现问题出在哪儿!后来突然想到,可能是函数返回的时候出的问题,不能光看函数的立即返回结果!

果然,这是一个属于:使用指向局部变量的指针作为函数返回值的例子!

 pointer * Func{

  return pointer = &
iTemp;

}

这样做会造成非常严重的后果!!!!

千万不要企图返回局变量堆栈上的指针,返回局部栈上的指针,你的指针就指向了该局部变量iTemp的地址,由于局部栈会在函数返回的时刻清栈,然而你的指针所指向的地址还是不变的。也就是说
pointer还是指向iTemp原来的那块内存,但是接着执行下来,那块内存的内容完全是不确定的!所以,导致你下次使用 函数返回指针 ret_pointer =
Func(); ret_pointer的内容完全不确定,会产生灾难性后果!!

先给出问题代码:


#include "pkt_analyzer.h"
#include "stdio.h"
#include "string.h"
#include "malloc.h"

extern PktUnit *pkt_analyzer(char *rx_buffer, int rx_len);

int main()
{
int i = 0;
int payload_len = 0;
u_int8 *my_payload = (u_int8 *)malloc(sizeof(u_int8));

PktUnit *ppu = 0;

char in_buffer[PKT_HDEADER_LEN + 7] = {0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0e,0x05,0x0d,0x2e,0x23,0x01,0xc2,0x0e,0x0be,0xff,0x03,0x04,0x05,0x06,0x07};

ppu = pkt_analyzer(in_buffer,sizeof(in_buffer));

printf("payload_len = %d\n",ppu->payload_len);
printf("pkt_len = %d \n",ppu->pkt_len);
printf("timestampe = %ul",ppu->pkt_hdr.timestamp);

memcpy(my_payload, ppu->payload,sizeof(u_int8)*ppu->payload_len);

for(i=0; i< ppu->payload_len ;i++){
printf("%x\n", *my_payload++);
}

free(my_payload);
return 0;
}


/*
* recv_pkt_analyzer.c
*
* Created on: 2014-5-7
* Author: fang ying
*/

/* @Function Description: Perform packet analysis
*
* @param
* @param
* @return
*/

#include "pkt_analyzer.h"
#include "stdlib.h"
#include "string.h"

#ifndef NULL
#define NULL 0
#endif

#define MakeDoubleWord(a,b,c,d,e,f,g,h) (((u_int64)(a & 0xff) << 56 )|((u_int64)(b & 0xff) << 48)|\
((u_int64)(c & 0xff) << 40 )|((u_int64)(d & 0xff) << 32)| ((u_int64)(e & 0xff) << 24 )|((u_int64)(f & 0xff) << 16)| ((u_int64)(g & 0xff) << 8 )|((u_int64)(h & 0xff) << 0 ))

#define MakeWord(a,b,c,d) (((u_int32)(a & 0xff) << 24 )|((u_int32)(b & 0xff) << 16)|\
((u_int32)(c & 0xff) << 8 ) |((u_int32)(d & 0xff) << 0))

PktUnit *pkt_analyzer(char *rx_buffer, int rx_len){

u_int32 get_class_id = 0;
u_int32 get_cmd_field = 0;
u_int64 get_timestamp = 0;
u_int32 get_parameter = 0;
u_int32 get_pkt_payload = 0;

PktUnit packet_rx;
PktUnit *pkt_unit = NULL;

/* first check the validity of rx buffer */
if(rx_buffer == NULL || rx_len <= 0){
return NULL;
}

get_class_id = MakeWord(rx_buffer[0],rx_buffer[1],rx_buffer[2],rx_buffer[3]);
/* get the class identification of the rx packet */
switch(get_class_id){
case CMD_DATA:
packet_rx.pkt_hdr.class_id = CMD_DATA;
break;
case SHORT_MSG:
packet_rx.pkt_hdr.class_id = SHORT_MSG;
break;
case LONG_MSG:
packet_rx.pkt_hdr.class_id = LONG_MSG;
break;
case EXTDATA_MSG:
packet_rx.pkt_hdr.class_id = EXTDATA_MSG;
break;
case CMD_EXCHANGE:
packet_rx.pkt_hdr.class_id = CMD_EXCHANGE;
break;
default:
return NULL;
}

/* check direction */
get_cmd_field = MakeWord(rx_buffer[8],rx_buffer[9],rx_buffer[10],rx_buffer[11]);
if(get_cmd_field != MASTER_2_TASK){
return NULL;
}else{
// fill the cmd field
packet_rx.pkt_hdr.cmd_field = get_cmd_field;
}

/* get parameter field */
get_parameter = MakeWord(rx_buffer[12],rx_buffer[13],rx_buffer[14],rx_buffer[15]);
packet_rx.pkt_hdr.para_field = get_parameter;

/* get timestamp information */
get_timestamp = MakeDoubleWord(rx_buffer[20],rx_buffer[21],rx_buffer[22],rx_buffer[23],
rx_buffer[24],rx_buffer[25],rx_buffer[26],rx_buffer[27]);
packet_rx.pkt_hdr.timestamp = get_timestamp;

/* get packet length */
packet_rx.pkt_len = rx_len;

/* analysis packet according to class id */
if(get_class_id == CMD_DATA){
packet_rx.payload_len = CMD_DATA_PAYLOAD_LEN;
}

if(get_class_id == SHORT_MSG){
switch(get_parameter){
case AUDIO_250MS:
packet_rx.payload_len = AUDIO_250MS_PAYLOAD_LEN;
break;
case SHORT_MSG_250MS:
packet_rx.payload_len = SHORT_MSG_250MS_PAYLOAD_LEN;
break;
case SHORT_MSG_500MS:
packet_rx.payload_len = SHORT_MSG_500MS_PAYLOAD_LEN;
break;
case KEYBOARD_250MS:
packet_rx.payload_len = KEYBOARD_250MS_PAYLOAD_LEN;
break;
case KEYBOARD_500MS:
packet_rx.payload_len = KEYBOARD_500MS_PAYLOAD_LEN;
break;
default:
return NULL;
}
}

if(get_class_id == LONG_MSG){
switch(get_parameter){
case LONG_MSG_500MS:
packet_rx.payload_len = LONG_MSG_500MS_PAYLOAD_LEN;
break;
case LONG_MSG_750MS:
packet_rx.payload_len = LONG_MSG_750MS_PAYLOAD_LEN;
break;
default:
return NULL;
}
}

if(get_class_id == EXTDATA_MSG){
switch(get_parameter){
case EXT_DATA_1P2K:
packet_rx.payload_len = EXT_DATA_1P2K_PAYLOAD_LEN;
break;
case EXT_DATA_2P4K:
packet_rx.payload_len = EXT_DATA_2P4K_PAYLOAD_LEN;
break;
case EXT_DATA_4P8K:
packet_rx.payload_len = EXT_DATA_4P8K_PAYLOAD_LEN;
break;
case EXT_DATA_9P6K:
packet_rx.payload_len = EXT_DATA_9P6K_PAYLOAD_LEN;
break;
case EXT_DATA_19P2K:
packet_rx.payload_len = EXT_DATA_19P2K_PAYLOAD_LEN;
break;
case EXT_DATA_25P6K:
packet_rx.payload_len = EXT_DATA_25P6K_PAYLOAD_LEN;
break;
case EXT_DATA_38P4K:
packet_rx.payload_len = EXT_DATA_38P4K_PAYLOAD_LEN;
break;
default:
return NULL;
}
}

if(get_class_id == CMD_EXCHANGE){
switch(get_parameter){
case SIGNALING_400MS_RECV_MODE:
break;
case AUDIO_250MS_RECV_MODE:
break;
case SHORT_MSG_250MS_RECV_MODE:
break;
case SHORT_MSG_500MS_RECV_MODE:
break;
case KEYBOARD_250MS_RECV_MODE:
break;
case KEYBOARD_500MS_RECV_MODE:
break;
case LONG_MSG_500MS_RECV_MODE:
break;
case LONG_MSG_750MS_RECV_MODE:
break;
case EXT_DATA_1P2K_RECV_MODE:
break;
case EXT_DATA_2P4K_RECV_MODE:
break;
case EXT_DATA_4P8K_RECV_MODE:
break;
case EXT_DATA_9P6K_RECV_MODE:
break;
case EXT_DATA_19P2K_RECV_MODE:
break;
case EXT_DATA_25P6K_RECV_MODE:
break;
case EXT_DATA_38P4K_RECV_MODE:
break;
default:
return NULL;
}
}

/* get payload */
packet_rx.payload = (int_8 *)malloc(sizeof(u_int8));
//packet_rx.payload = &rx_buffer[PKT_HDEADER_LEN];
memcpy(packet_rx.payload,&rx_buffer[PKT_HDEADER_LEN],sizeof(u_int8)*packet_rx.payload_len);

pkt_unit = &packet_rx;
return (pkt_unit);
}


/*
* pkt_analyzer.h
*
* Created on: 2014-5-7
* Author: fang ying
*/

#ifndef _PKT_ANALYZER_H_
#define _PKT_ANALYZER_H_

/* type defination */
typedef char int_8;
typedef unsigned char u_int8;
typedef unsigned short u_int16;
typedef unsigned int u_int32;
typedef unsigned long long u_int64;

typedef struct PktHeader_t{
u_int32 class_id; /* class identification unique number*/
u_int32 board_id; /* board identification */
u_int32 cmd_field; /* command field */
u_int32 para_field; /* parameter field */
u_int64 freq_info; /* frequency information */
u_int32 channel_SNR; /* SNR of the channel */
u_int64 timestamp; /* timestamp */

}PktHeader;

typedef struct PktUnit_t{
PktHeader pkt_hdr; /* packet header */
int_8 *payload; /* data payload */
u_int32 payload_len; /* packet payload length */
u_int32 pkt_len; /* packet total length */
}PktUnit;

/* constriant definations */
#define PKT_HDEADER_LEN 28

/* class identification */
#define CMD_DATA 0x1 /* command data unit */
#define SHORT_MSG 0x2 /* short message data unit */
#define LONG_MSG 0x3 /* long message data unit */
#define EXTDATA_MSG 0x4 /* extra data frame unit */
#define CMD_EXCHANGE 0x5 /* command exchange unit */

/* board identification */
#define MASTER_BOARD 0x0
#define TASK_BOARD 0x1

/* command field of command data unit */
#define MASTER_2_TASK 0x1
#define TASK_2_MASTER 0x2

/******************** command data unit header explain **********************/
/* parameter field of command data unit */
#define FREQUENCY_PAYLOAD_INFO 0x1
#define FREQUENCY_INFO_ONLY 0x2
#define PAYLOAD_INFO_ONLY 0x3
#define RESERVED 0x4

#define SYN_CHECKED 0x1
#define RECEIVE_COMPLETE 0x2
#define EARLY_TX_SUCESS 0x3
#define EARLY_TX_FAILED 0x4

/******************** short and long message data unit header explain ****************/
/* parameter field of short message interact unit */
#define AUDIO_250MS 0x1
#define SHORT_MSG_250MS 0x2
#define SHORT_MSG_500MS 0x3
#define KEYBOARD_250MS 0x4
#define KEYBOARD_500MS 0x5
#define LONG_MSG_500MS 0x6
#define LONG_MSG_750MS 0x7
#define EXT_DATA_1P2K 0x8
#define EXT_DATA_2P4K 0x9
#define EXT_DATA_4P8K 0x10
#define EXT_DATA_9P6K 0x11
#define EXT_DATA_19P2K 0x12
#define EXT_DATA_25P6K 0x13
#define EXT_DATA_38P4K 0x14

/* length constraints of message */
#define CMD_DATA_PAYLOAD_LEN 7
#define AUDIO_250MS_PAYLOAD_LEN 62
#define SHORT_MSG_250MS_PAYLOAD_LEN 94
#define SHORT_MSG_500MS_PAYLOAD_LEN 94
#define KEYBOARD_250MS_PAYLOAD_LEN 94
#define KEYBOARD_500MS_PAYLOAD_LEN 94
#define LONG_MSG_500MS_PAYLOAD_LEN 478
#define LONG_MSG_750MS_PAYLOAD_LEN 766
#define EXT_DATA_1P2K_PAYLOAD_LEN 574
#define EXT_DATA_2P4K_PAYLOAD_LEN 574
#define EXT_DATA_4P8K_PAYLOAD_LEN 574
#define EXT_DATA_9P6K_PAYLOAD_LEN 1152
#define EXT_DATA_19P2K_PAYLOAD_LEN 2304
#define EXT_DATA_25P6K_PAYLOAD_LEN 3456
#define EXT_DATA_38P4K_PAYLOAD_LEN 4608

/**************** command exchange unit header explain *****************/
/* parameter field of command exchange unit */
#define SIGNALING_400MS_RECV_MODE 0x0
#define AUDIO_250MS_RECV_MODE 0x1
#define SHORT_MSG_250MS_RECV_MODE 0x2
#define SHORT_MSG_500MS_RECV_MODE 0x3
#define KEYBOARD_250MS_RECV_MODE 0x4
#define KEYBOARD_500MS_RECV_MODE 0x5
#define LONG_MSG_500MS_RECV_MODE 0x6
#define LONG_MSG_750MS_RECV_MODE 0x7
#define EXT_DATA_1P2K_RECV_MODE 0x8
#define EXT_DATA_2P4K_RECV_MODE 0x9
#define EXT_DATA_4P8K_RECV_MODE 0x10
#define EXT_DATA_9P6K_RECV_MODE 0x11
#define EXT_DATA_19P2K_RECV_MODE 0x12
#define EXT_DATA_25P6K_RECV_MODE 0x13
#define EXT_DATA_38P4K_RECV_MODE 0x14

#endif /* PKT_ANALYZER_H_ */

问题出在这个地方:

这里使用了指向局部变量的指针,并作为函数的返回指针。

改正后的代码如下


/*
* recv_pkt_analyzer.c
*
* Created on: 2014-5-7
* Author: fang ying
*/

/* @Function Description: Perform packet analysis
*
* @param
* @param
* @return
*/

#include "pkt_analyzer.h"
#include "stdlib.h"
#include "string.h"

#ifndef NULL
#define NULL 0
#endif

#define MakeDoubleWord(a,b,c,d,e,f,g,h) (((u_int64)(a & 0xff) << 56 )|((u_int64)(b & 0xff) << 48)|\
((u_int64)(c & 0xff) << 40 )|((u_int64)(d & 0xff) << 32)| ((u_int64)(e & 0xff) << 24 )|((u_int64)(f & 0xff) << 16)| ((u_int64)(g & 0xff) << 8 )|((u_int64)(h & 0xff) << 0 ))

#define MakeWord(a,b,c,d) (((u_int32)(a & 0xff) << 24 )|((u_int32)(b & 0xff) << 16)|\
((u_int32)(c & 0xff) << 8 ) |((u_int32)(d & 0xff) << 0))

PktUnit *pkt_analyzer(char *rx_buffer, int rx_len){

u_int32 get_class_id = 0;
u_int32 get_cmd_field = 0;
u_int64 get_timestamp = 0;
u_int32 get_parameter = 0;
u_int32 get_pkt_payload = 0;

PktUnit *packet_rx = (PktUnit *)malloc(sizeof(PktUnit));

/* first check the validity of rx buffer */
if(rx_buffer == NULL || rx_len <= 0){
return NULL;
}

get_class_id = MakeWord(rx_buffer[0],rx_buffer[1],rx_buffer[2],rx_buffer[3]);
/* get the class identification of the rx packet */
switch(get_class_id){
case CMD_DATA:
packet_rx->pkt_hdr.class_id = CMD_DATA;
break;
case SHORT_MSG:
packet_rx->pkt_hdr.class_id = SHORT_MSG;
break;
case LONG_MSG:
packet_rx->pkt_hdr.class_id = LONG_MSG;
break;
case EXTDATA_MSG:
packet_rx->pkt_hdr.class_id = EXTDATA_MSG;
break;
case CMD_EXCHANGE:
packet_rx->pkt_hdr.class_id = CMD_EXCHANGE;
break;
default:
return NULL;
}

/* check direction */
get_cmd_field = MakeWord(rx_buffer[8],rx_buffer[9],rx_buffer[10],rx_buffer[11]);
if(get_cmd_field != MASTER_2_TASK){
return NULL;
}else{
// fill the cmd field
packet_rx->pkt_hdr.cmd_field = get_cmd_field;
}

/* get parameter field */
get_parameter = MakeWord(rx_buffer[12],rx_buffer[13],rx_buffer[14],rx_buffer[15]);
packet_rx->pkt_hdr.para_field = get_parameter;

/* get timestamp information */
get_timestamp = MakeDoubleWord(rx_buffer[20],rx_buffer[21],rx_buffer[22],rx_buffer[23],
rx_buffer[24],rx_buffer[25],rx_buffer[26],rx_buffer[27]);
packet_rx->pkt_hdr.timestamp = get_timestamp;

/* get packet length */
packet_rx->pkt_len = rx_len;

/* analysis packet according to class id */
if(get_class_id == CMD_DATA){
packet_rx->payload_len = CMD_DATA_PAYLOAD_LEN;
}

if(get_class_id == SHORT_MSG){
switch(get_parameter){
case AUDIO_250MS:
packet_rx->payload_len = AUDIO_250MS_PAYLOAD_LEN;
break;
case SHORT_MSG_250MS:
packet_rx->payload_len = SHORT_MSG_250MS_PAYLOAD_LEN;
break;
case SHORT_MSG_500MS:
packet_rx->payload_len = SHORT_MSG_500MS_PAYLOAD_LEN;
break;
case KEYBOARD_250MS:
packet_rx->payload_len = KEYBOARD_250MS_PAYLOAD_LEN;
break;
case KEYBOARD_500MS:
packet_rx->payload_len = KEYBOARD_500MS_PAYLOAD_LEN;
break;
default:
return NULL;
}
}

if(get_class_id == LONG_MSG){
switch(get_parameter){
case LONG_MSG_500MS:
packet_rx->payload_len = LONG_MSG_500MS_PAYLOAD_LEN;
break;
case LONG_MSG_750MS:
packet_rx->payload_len = LONG_MSG_750MS_PAYLOAD_LEN;
break;
default:
return NULL;
}
}

if(get_class_id == EXTDATA_MSG){
switch(get_parameter){
case EXT_DATA_1P2K:
packet_rx->payload_len = EXT_DATA_1P2K_PAYLOAD_LEN;
break;
case EXT_DATA_2P4K:
packet_rx->payload_len = EXT_DATA_2P4K_PAYLOAD_LEN;
break;
case EXT_DATA_4P8K:
packet_rx->payload_len = EXT_DATA_4P8K_PAYLOAD_LEN;
break;
case EXT_DATA_9P6K:
packet_rx->payload_len = EXT_DATA_9P6K_PAYLOAD_LEN;
break;
case EXT_DATA_19P2K:
packet_rx->payload_len = EXT_DATA_19P2K_PAYLOAD_LEN;
break;
case EXT_DATA_25P6K:
packet_rx->payload_len = EXT_DATA_25P6K_PAYLOAD_LEN;
break;
case EXT_DATA_38P4K:
packet_rx->payload_len = EXT_DATA_38P4K_PAYLOAD_LEN;
break;
default:
return NULL;
}
}

if(get_class_id == CMD_EXCHANGE){
switch(get_parameter){
case SIGNALING_400MS_RECV_MODE:
break;
case AUDIO_250MS_RECV_MODE:
break;
case SHORT_MSG_250MS_RECV_MODE:
break;
case SHORT_MSG_500MS_RECV_MODE:
break;
case KEYBOARD_250MS_RECV_MODE:
break;
case KEYBOARD_500MS_RECV_MODE:
break;
case LONG_MSG_500MS_RECV_MODE:
break;
case LONG_MSG_750MS_RECV_MODE:
break;
case EXT_DATA_1P2K_RECV_MODE:
break;
case EXT_DATA_2P4K_RECV_MODE:
break;
case EXT_DATA_4P8K_RECV_MODE:
break;
case EXT_DATA_9P6K_RECV_MODE:
break;
case EXT_DATA_19P2K_RECV_MODE:
break;
case EXT_DATA_25P6K_RECV_MODE:
break;
case EXT_DATA_38P4K_RECV_MODE:
break;
default:
return NULL;
}
}

/* get payload */
packet_rx->payload = (int_8 *)malloc(sizeof(u_int8));
//packet_rx.payload = &rx_buffer[PKT_HDEADER_LEN];
memcpy(packet_rx->payload,&rx_buffer[PKT_HDEADER_LEN],sizeof(u_int8)*packet_rx->payload_len);
return packet_rx;
}

上面修改的地方,我定义了一个指针,并且动态申请了空间后面就对了。其思想是基于:

因为函数中的局部变量在函数调用结束后就会被释放;这句话是对的,局部变量超出其作用域后就会被释放掉
所以如果你在函数内部定义一个指针,并申请了空间;这句不怎么对,因为只查动态申请的内存都是在堆中申请,不会被释放掉

但是,如果是使用字符串指针形式,char
*str = "hello world"这个叫字符串字面常量。储存在静态区,是只读!!!!的所以可以返回


#include<stdio.h>

char *returnstr()
{
char *str="Hello!World!";
printf("In returnstr, addr of str:\t%p\n", str);
return str; //"Hello!world!\n";
}
int main()
{
char *str=returnstr();
printf("In main, addr of str:\t%p\n", str);
printf("%s\n", str);
return 0;
}

函数中的变量存储空间是在栈上分配的,函数结束时自动释放,所以不能返回这样的变量,即使你返回了,就像7楼所说的,也得到了正确的值,请不要高兴,这是因为那块内存还没有被占用,值还没有改变,所以你得到了正确的值,有一种情况是可以返回局部指针的,就是在堆上动态分配存储空间,这些空间在函数结束时不会自动释放,但是需要自己释放,所以得记住,要是忘记了就漏掉了。

切勿使用:指向局部变量的指针作为函数的返回指针!

时间: 2024-08-28 12:01:15

切勿使用:指向局部变量的指针作为函数的返回指针!的相关文章

C-const和static的区别, 指针作为函数的返回值, 指向函数的指针, 枚举

const和static的区别 const ——只读, 只在声明中使用 1 const int num = 10; 2 int const num = 10; num变量只读, 不能修改 1 const int arr[4] = {10, 20, 30, 40 }; 2 int const arr[4] = {10, 20, 30 ,40 }; 数组的元素的值不能被修改, 只读 1 const int *p1 = &num; 2 int const *p1 = &num; 无法通过p1指针

新手,对函数,函数指针,回调函数, 函数指针作为函数的返回值和block的一些见解

很多初学者,学c语言时,看到函数都觉得难,我也是,一开始觉得函数太难了,后来慢慢就理解了 第一:函数 在c语言中最简单的函数一般有四种: 1, 无返回值, 无参数. 2, 无返回值,有参数. 3, 有返回值,无参数. 4, 有返回值,有参数 1, 无返无参  定义方式:      void 函数名(); 一般不怎么用这种形式的函数,可用来输出,打印 void functionOne() { printf("无返回值,无参数"); // 没有返回值不能写return } int main

c++中使用指针调用函数和使用指针调用类对象的()重载函数

使用函数指针时,指针可以像函数名一样,直接加括号和参数列表调用:也可先解引用再调用 1 1 //include directories... 2 2 using namespace std; 3 3 void testFun() 4 4 { 5 5 cout<<"this is a test"<<endl; 6 6 } 7 7 int main(int argc,char**argv) 8 8 { 9 9 auto *pFun=testFun; 10 10 pF

学习笔记之14-返回指针的函数与指向函数的指针

一.返回指针的函数 指针也是C语言中的一种数据类型,因此一个函数的返回值肯定可以是指针类型的. 返回指针的函数的一般形式为:类型名 * 函数名(参数列表) 比如下面这个函数,返回一个指向char类型变量的指针 1 // 将字符串str中的小写字母变成大写字母,并返回改变后的字符串 2 // 注意的是:这里的参数要传字符串变量,不能传字符串常量 3 char * upper(char *str) { 4 // 先保留最初的地址.因为等会str指向的位置会变来变去的. 5 char *dest =

【C语言】-返回指针的函数与指向函数的指针

本文目录 前言 一.返回指针的函数 二.指向函数的指针 说明:这个C语言专题,是学习iOS开发的前奏.也为了让有面向对象语言开发经验的程序员,能够快速上手C语言.如果你还没有编程经验,或者对C语言.iOS开发不感兴趣,请忽略 回到顶部 前言 前面我们花了接近3个章节学习指针,应该都感受到指针的强大了吧.指针可以根据地址直接操作内存中的数据,使用得当的话,不仅能使代码量变少,还能优化内存管理.提升程序性能.关于指针的内容还非常多,比如指针数组.指向数组的指针.指向指针的指针,呵呵,看到这些名字是否

【C语言】14-返回指针的函数与指向函数的指针

前言 前面我们花了接近3个章节学习指针,应该都感受到指针的强大了吧.指针可以根据地址直接操作内存中的数据,使用得当的话,不仅能使代码量变少,还能优化内存管理.提升程序性能.关于指针的内容还非常多,比如指针数组.指向数组的指针.指向指针的指针,呵呵,看到这些名字是否都觉得头大了,不过我就暂时不在博客中讲解这些内容了,我只讲述在iOS开发中指针的最常见用法,比如这一章的内容----返回指针的函数 与 指向函数的指针 回到顶部 一.返回指针的函数 指针也是C语言中的一种数据类型,因此一个函数的返回值肯

C语言 14-返回指针的函数与指向函数的指针

本文目录 前言 一.返回指针的函数 二.指向函数的指针 说明:这个C语言专题,是学习iOS开发的前奏.也为了让有面向对象语言开发经验的程序员,能够快速上手C语言.如果你还没有编程经验,或者对C语言.iOS开发不感兴趣,请忽略. 前言 前面我们花了接近3个章节学习指针,应该都感受到指针的强大了吧.指针可以根据地址直接操作内存中的数据,使用得当的话,不仅能使代码量变少,还能优化内存管理.提升程序性能.关于指针的内容还非常多,比如指针数组.指向数组的指针.指向指针的指针,呵呵,看到这些名字是否都觉得头

了解指针(5)-- 指针和函数

就像数组名是指向数组的第一个元素的常指针一样,函数名也是指向函数的常指针.可以声明一个指向函数的指针变量,并且用这个指针调用其他函数(只要这个函数和你的函数指针在签名.返回.参数值方面一致即可). 例1: long  (* fun) (int) 上面就是一个函数指针,该指针返回值类型是long,所带的参数类型是int. 例2: int fun(char *,int); int (*pfun)(char *,int); pfun=fun; int a=(*pfun)("abcdefg",

解析 指针数组,数组指针,函数指针

一 :关于指针和堆的内存分配 指针数组 : 一个数组里放的都是指针,我们把他叫做指针数组 int * a[10]; 由于它是一个数组,他是不能从堆空间里申请空间的. 只能做个循环,每个元素去申请空间,或者每个元素去指向另外的地址空间. 数组指针 : 一个指向一唯或者多唯数组的指针: int * b=new int[10]; 指向一唯数组的指针b ; 一些例子: int (*b2)[10]=new int[10][10]; 注意,这里的b2指向了一个二唯int型数组的首地址. 注意,这里的b2的类