然而,我还没有看到有关必须初始化char指针地址的强制性要求的相关内容。
例如,这段代码是否正确,是否需要指针地址初始化?
char *p_message;
*p_message = "Pointer";
char *p_message;
*p_message = "Pointer";
我不太确定你所说的“数字指针”与“字符指针”的区别。在C语言中,char
是一种整数类型,因此它是算术类型。无论如何,无论是指向 char
的指针还是其他类型的指针,在初始化时都不是必需的。
您的代码错误在于使用了 *p_message
而不是 p_message
来设置指针的值:
*p_message = "Pointer" // Error!
这是错误的,因为考虑到p_message
是指向char
的指针,*p_message
应该是一个char
,而不是整个字符串。但是在首次声明char
指针时需要初始化并不是必须的。所以下面的代码是可行的:
char *p_message;
p_message = "Pointer";
char *p_message;
*p_message = 'A';
但是这与指针是否正确初始化无关。即使作为初始化,以下代码也会失败:
char *p_message = 'A';
这个错误的原因和 int *a = 5;
的错误原因相同。那么为什么会出错呢?为什么下面的代码可以正常工作:
char *p_message;
p_message = "Pointer";
char *p_message;
*p_message = 'A';
p_message =“Pointer”
时,你正在将p_message
赋予字符串文字“Pointer”
的第一个字符'P'
的地址。 字符串字面值位于不同的内存段中,它们被认为是不可变的,并且它们的内存不需要在堆栈或堆上专门分配。int
一样,char
也需要在堆栈或堆上分配。 要么需要声明一个char
变量以便在堆栈上有内存:char myChar;
char *pChar;
pChar = &myChar;
*pChar = 'A';
或者你需要在堆上动态分配内存:
char* pChar;
pChar = malloc (1); // or pChar = malloc (sizeof (char)), but sizeof(char) is always 1
*pChar = 'A';
char
指针与int
或double
指针不同,因为它们可以用于指向字符串文字,您不必在堆栈(静态)或堆(动态)上分配内存。我认为这可能是您实际的问题,与内存分配有关而不是初始化。
如果您真正询问的是初始化而不是内存分配:指针变量在初始化方面与任何其他变量没有区别。就像未初始化的int
变量在初始化之前会具有一些垃圾值一样,指针在初始化之前也会具有一些垃圾值。如您所知,您可以声明一个变量:
double someVal; // no initialization, will contain garbage value
并且在代码的后面有一个分配操作来设置它的值:
someVal = 3.14;
int ary [] = { 1, 2, 3, 4, 5 };
int *ptr; // no initialization, will contain garbage value
ptr = ary;
ptr
没有被初始化,但是后来被分配了数组第一个元素的地址。NULL
,因为你可能会在分配任何实际(非垃圾)值之前无意中尝试对指针进行解引用,而对垃圾地址进行解引用可能会导致程序崩溃,或者更糟糕的是,可能会破坏内存。但这与始终将变量(例如int
)初始化为零并不完全不同,当您声明它们时。如果您的代码在设置其预期值之前错误地使用变量,我不确定该值是零、NULL
还是垃圾,是否真的很重要。
编辑。OP在评论中问:您说“字符串字面量位于不同的内存段中,它们被认为是不可变的,并且不需要在堆栈或堆上专门分配内存”,那么分配是如何发生的?
这就是语言的工作方式。在C语言中,字符串字面量是语言的一个元素。 C11标准在§6.4.5中指定,当编译器将源代码转换为机器语言时,它应该将任何双引号中的字符序列转换为char
(或wchar_t
如果它们是宽字符)的静态数组,并附加一个NUL
字符作为数组的最后一个元素。然后,此数组被视为不可变。标准说:如果程序尝试修改这样的数组,则行为未定义。
因此,基本上,当您有像这样的语句时:
char *p_message = "Pointer";
"Pointer"
" 实现为一个静态、不可变、以 NUL
结尾的 char
数组,存储在内存中的某个位置。通常情况下,实现会将这样的字符串字面量放置在只读内存区域,例如文本块(与程序指令一起)。但这并非必须。对于特定编译器如何处理此数组/以 NUL
结尾的 char
/字符串字面量的内存分配方式,取决于该编译器的具体实现。然而,由于该数组存在于内存中的某处,因此您可以拥有指向它的指针,因此上述语句在法律上是有效的。char
,您可以拥有指向该字符串的 char
指针,但您无法更改字符串字面量本身。'A'
)或整数常量(如 5
)指定了此行为。设置存储这些常量/非字符串字面量的内存是程序员的责任。因此,当编译器遇到类似以下语句的情况时:char *charPtr = 'A'; // illegal!
int *intPtr = 5; // illegal!
初始化不是必需的,无论指针指向什么类型。唯一的要求是您不能尝试使用未初始化的指针(从未被分配)进行任何操作。
但是,出于美观和维护原因,应在可能的情况下始终进行初始化(即使只是将其初始化为NULL
)。
NULL
)指针变量是我个人认为的一个好习惯。请注意,如果该初始化是无用的(因为变量在第一次使用之前已设置),优化编译器将跳过它。 - Basile Starynkevitchchar *p_message = "指针";
。 - Oliver Charlesworthchar = var; p_message = &var
这样的东西会更好吧? - Heikki首先,char
是一种数字类型,所以你问题中的区分是没有意义的。按照你的示例代码编写,它甚至无法编译:
char *p_message;
*p_message = "Pointer";
char *p_message;
p_message = "Pointer";
p_message
指向字符串字面值。然而,这可能或可能不是你想要的。另一方面,如果你写成了以下代码:char *p_message;
*p_message = 'P';
或者
char *p_message;
strcpy(p_message, "Pointer");
*
运算符应用于无效指针,或者(第二个示例)向期望指向能够存储正确数量字符的有效对象的标准库函数传递无效指针,则代码将调用未定义行为。虽然不是必须的,但建议使用它以保持代码风格的整洁。 另外,你发布的代码完全错误且无法运行,但你知道这一点并只是为了快速示例,对吧?