我总是理解指针如下:
int x = 5;
int *y = &x;
printf("%d", *y);
x
访问该值。y
,将其内存位置设置为x
的内存位置。y
持有的地址的值。然而,我可以同时做char *string = "neato"
并且它完全有效。对我来说,这看起来像“创建一个字符指针,保持内存地址'neato'”。这有什么用呢?
此外,如果我设置它,我会尝试将其作为*string = "more neat"
,但这会产生错误。我需要做string = "more neat"
。第一次尝试直观地看起来像“将存储在由字符串保存的内存地址的值更改为'更整洁'”,但它不起作用。第二个看起来像“对于'字符串'所持有的内存地址,将其更改为'更多neato'。这对我来说完全没有意义。
我有什么困惑?如果为了访问存储在指针中的值我需要printf("%d", *pointer)
,那么如何设置的值不是沿着这些行?
答案 0 :(得分:2)
一元*
运算符有两个不同(但相关)的目的。在声明中,它表示该类型是指针类型,但并不意味着指针被解除引用。
在表达式中使用时,表示引用指针。这就是为什么你的例子在它声明的地方工作的原因,但当你取消引用它时你不能分配(因为如果你可以修改字符串文字,那么分配的适当类型将是一个字符。)
在声明之外执行此操作的等效方式如下:
const char *s = "hello"; /* initialize pointer value */
s = "goodbye"; /* assign to pointer value */
上述初始化和赋值是等效的。
答案 1 :(得分:1)
"neato"
属于const char[]
类型。在适当的时候,数组会衰减到指针,因此赋值是指向另一个的指针。
然后你的指针应该是const char
。写入由字符串文字占用的内存位置会调用未定义的行为。但这是有效的:
char str[] = "neato";
str[0] = 'p';
此外,如果我设置它,我会尝试将其作为* string =“more neat”
好吧,你有一个指向 char 的指针,所以这个赋值没有意义(也就是我上面写的关于写一个字符串文字的内容。)
答案 2 :(得分:1)
char *
和字符串“neato”的基本类型是char;字符串文字只是字符数组,通常位于只读地址中。 “n”必须位于地址中(因为必须是下一个字符“e”,依此类推)。该地址存储在变量char *ptr
;
问题的第二部分是为什么*ptr = "more neat";
无效。
*var
取消引用地址 - 在这种情况下是1个字符的宽内存地址,其中包含字符'n'。您不能将新字符串文字的地址(可能以4或8字节表示)放入单个字符;你也不能把9个字符和终止的ascii-zero放在里面。
我们可以通过对16位(Big Endian)机器进行内存转储来研究这个问题;
0FFE: .. .. // other variables, return addresses etc.
1000: F0 00 // The pointer "var" is located here
1002: // Top of stack
F000: "n" "e" "a" "t" "o" 00 // Address of constant string is F000
F006: "m" "o" "r" "e" ... // Address of next string is F006
*var
访问F000的单字节内存。 var
本身位于地址0000,并且在此机器中有两个字节,因为地址在这里是16位宽。新作业var="more neat"
之后;内存转储是:
1000: F0 06 // Pointer holds a new address
答案 3 :(得分:0)
例如,
char *ptr = "neato";
char arr[] = "neato";
完全不同。 ptr 是指向字符串文字“neato”的指针,编译器通常将字符串文字存储在只读内存中。因此,您无法将字符串文字 ptr 更改为,但您可以更改 ptr 的值,即地址。
*ptr = "more neat"; // error, even if *ptr were writable, it should be a character
*ptr = 'b'; // error
ptr = "more neat"; // ok, you just create another string literal and ptr now points to it
第二个只是
的缩写char arr[] = {'n', 'e', 'a', 't', 'o', '\0'};
在这种情况下,您可以更改数组中的字符,但不能更改arr的地址(是的,它是一个数组)
*arr = 'b'; // ok
arr = "more neat" // error, the value of arr, namely the address of the array cannot be changed
初始化和分配是不同的,即使它们看起来非常相似,但操作的含义通常是不同的。