C指针地址初始化是否必要?

Hei*_*kki 3 c pointers allocation memory-address

我正在以自学成才的方式学习C编程.我知道必须始终静态或动态地初始化数字指针地址.

但是,我还没有读到有关初始化char指针地址的强制要求.

例如,这段代码是正确的,还是需要指针地址初始化?

char *p_message;
*p_message = "Pointer";
Run Code Online (Sandbox Code Playgroud)

ver*_*ose 5

我不完全确定你的意思是"数字指针"而不是"字符指针".在C中,a char是整数类型,因此它是算术类型.在任何情况下,指针都不需要初始化,无论它是否是指针char.

您的代码错误地使用*p_message而不是p_message设置指针的值:

*p_message = "Pointer"          // Error!
Run Code Online (Sandbox Code Playgroud)

这是错误的,因为给定的p_message是指针char,*p_message应该是char,而不是整个字符串.但是,char首次声明时需要初始化指针,这不是必需的.所以这没关系:

char *p_message;
p_message = "Pointer";
Run Code Online (Sandbox Code Playgroud)

我猜你的一部分困惑来自于这不合法的事实:

char *p_message;
*p_message = 'A';
Run Code Online (Sandbox Code Playgroud)

但是,这与指针是否正确初始化无关.即使是初始化,这也会失败:

char *p_message = 'A'; 
Run Code Online (Sandbox Code Playgroud)

错误的原因int *a = 5;是错误的.那为什么这是错的?为什么这样做:

char *p_message;
p_message = "Pointer";
Run Code Online (Sandbox Code Playgroud)

但这失败了?

char *p_message;
*p_message = 'A';
Run Code Online (Sandbox Code Playgroud)

这是因为没有分配内存'A'.如果有p_message = "Pointer",则指定字符串文字p_message的第一个字符的地址.字符串文字存在于不同的内存段中,它们被认为是不可变的,并且它们的内存不需要在堆栈或堆上专门分配.'P'"Pointer"

但是char,像ints 一样,需要在堆栈或堆上分配.您需要声明一个char变量,以便堆栈上有内存:

char myChar;
char *pChar;
pChar = &myChar;
*pChar = 'A';
Run Code Online (Sandbox Code Playgroud)

或者您需要在堆上动态分配内存:

char* pChar;
pChar = malloc (1); // or pChar = malloc (sizeof (char)), but sizeof(char) is always 1
*pChar = 'A';
Run Code Online (Sandbox Code Playgroud)

因此,在某种意义上,char指针与intdouble指针不同,因为它们可以用于指向字符串文字,您不必在堆栈上(静态地)或堆(动态地)分配内存.我认为这可能是你的实际问题,与内存分配而不是初始化有关.

如果您真的在询问初始化而不是内存分配:指针变量与初始化方面的任何其他变量没有区别.就像未初始化的int变量在初始化之前会有一些垃圾值一样,指针在初始化之前也会有一些垃圾值.如您所知,您可以声明一个变量:

double someVal;    // no initialization, will contain garbage value
Run Code Online (Sandbox Code Playgroud)

然后在代码中有一个设置其值的赋值:

someVal = 3.14;
Run Code Online (Sandbox Code Playgroud)

类似地,使用指针变量,您可以使用以下内容:

int ary [] = { 1, 2, 3, 4, 5 };
int *ptr;          // no initialization, will contain garbage value
ptr = ary;
Run Code Online (Sandbox Code Playgroud)

这里,ptr没有初始化为任何东西,但后来被分配了数组的第一个元素的地址.

有些人可能会说初始化指针总是好的,至少是这样NULL,因为你可能会在指针被分配任何实际(非垃圾)值之前无意中尝试取消引用指针,并且取消引用垃圾地址可能会导致程序崩溃,或者更糟糕的是,可能会破坏记忆.但是,int当你声明变量时,总是将变量初始化为零,这并不完全不同.如果你的代码在设置其值之前错误地使用了一个变量,那么我不确定这个值是零NULL,还是垃圾都很重要.


编辑.OP在评论中提出:你说"字符串文字存在于不同的内存段中,它们被认为是不可变的,并且它们的内存不需要在堆栈或堆上专门分配",那么分配是如何发生的?

这就是语言的运作方式.在C中,字符串文字是语言的一个元素.C11标准在§6.4.5中规定,当编译器将源代码转换为机器语言时,它应该将双引号中的任何字符序列转换为静态数组char(或者wchar_t如果它们是宽字符)并附加一个NUL字符作为数组的最后一个元素.然后将该数组视为不可变的.标准说:If the program attempts to modify such an array, the behavior is undefined.

所以基本上,当你有一个声明如下:

char *p_message = "Pointer";
Run Code Online (Sandbox Code Playgroud)

该标准要求将双引号字符序列"Pointer"实现为内存NULchar某处的静态,不可变,终止的数组.通常,实现将这样的字符串文字放在存储器的只读区域中,例如文本块(以及程序指令).但这不是必需的.给定实现处理此数组/ NUL终止的char/ string文字序列的内存分配的确切方式取决于特定的编译器.但是,因为此数组存在于内存中的某个位置,所以可以指向它,因此上述语句可以合法地工作.

与函数指针类比可能很有用.就像函数的代码作为指令序列存在于内存中一样,你可以有一个指向该代码的函数指针,但你不能更改函数代码本身,所以字符串文字作为序列存在于内存中的char,你可以有一个char指向该字符串的指针,但你不能改变字符串文字本身.

C标准仅为字符串文字指定此行为,而不是像字符常量'A'或整数常量那样5.留出内存来保存这些常量/非字符串文字是程序员的责任.所以当编译器遇到如下语句时:

char *charPtr = 'A';    // illegal!
int *intPtr = 5;        // illegal!
Run Code Online (Sandbox Code Playgroud)

编译器不知道如何处理它们.程序员没有在堆栈或堆上留出这样的内存来保存这些值.与字符串文字不同,编译器也不会为它们留出任何内存.所以这些陈述是非法的.

希望这更清楚.如果没有,请再次发表评论,我会尝试澄清一些.