我在Standard,K& R C中发言。
假设:
const char a[] = {1, 2, 3};
const char *p = NULL;
这两个陈述是否相同:
*p = a;
p = a;
他们每个人都会在片段的第三行。
1和2肯定看起来不一样。
两者之间的区别是什么?
答案 0 :(得分:4)
没有
p = a
初始化指针指向别的东西(通常它会复制另一个指针,或者你会指向一个引用,ala p = &a
。
*p = a
初始化p指的是什么。你是“解除引用”(看)p指向的东西。如果p在您的示例中指向NULL,则会崩溃(这很好!您不想意外访问某些内容并弄乱您的程序)。
在这种情况下,p = a
将指向数组a []的第一个,*p = a
将尝试更改数组的第一个(它将无效;您已将其声明常数)。
这是C ++中的一个小示例程序,其语法与C语言几乎完全相同。
#include <iostream>
int main()
{
char arr[5] { 'a', 'b', 'c' }; // arr[3] and arr[4] are set to 0
char *ptr = arr; //point to 'a'
for (int i = 0; i != 5; i++)
{
*ptr = 'f'; //this changes the array
ptr++; //this changes what the pointer points to; moves it to next in array
}
for (int i = 0; i != 5; i++)
{
std::cout << *ptr << " ";
}
//outputs f f f f f
}
答案 1 :(得分:2)
*运算符就是我们所说的dereference operator。要了解它的作用,你必须准确理解指针是什么。
当你这样做时
char *p;
“变量”p不使用与普通char相同的内存量,它使用更多内存:它使用正确识别计算机内存位置所需的内存量。所以,假设您使用的是32位架构,变量p占用4个字节(不是您期望从char中获得的1个字节)。
所以,当你这样做时
p = a;
你清楚地看到你正在改变变量p的内容,也就是说,你在其中放入另一个32位数字:你正在改变它所指向的地址。
执行该行后,p的值是字符数组a的内存地址。
现在为取消引用运算符。当你这样做
*p = 'Z';
您告诉编译器您要将值'Z'存储在p指向的地址上。因此,p的值在此行之后保持不变:它继续指向相同的地址。 此地址的值已更改,现在包含“Z”。
所以,
的最终效果char a[] = {'a', 'b', 'c'};
char p = a;
*p = 'Z';
与将数组a的第一个位置更改为“Z”相同,即:
char a[] = {'a', 'b', 'c'};
a[0] = 'Z';
注意:使指针指向数组时有区别:包含数组的变量只包含第一个元素的地址,因此 a 是与“数组的起始地址”相同。
通常你会看到&amp;运营商。它是一个用于获取变量的内存地址的运算符。例如:
int number = 42;
int pointer = &number;
printf("%d", *pointer);
我们拥有所有这些。第一行创建一个整数变量并在其中存储42个。
第二行创建一个指向整数的指针,并在其中存储 变量编号的地址。
第三行重新指针指向的地址上的值。
因此,诀窍是将* x指向x 指向的地址为,将&x;读为 x 的地址。
答案 2 :(得分:1)
第一个取消引用空指针,并尝试为其分配数组的地址。这将是编译器错误,因为char != char []
。如果不是,它可能会崩溃。
第二个设置p
以指向数组。
答案 3 :(得分:1)
这是我学习C时使用的技巧(现在仍在使用)。
每当您在代码中看到变量前面的*时,会自动将其读作“指向的内容”。
因此,您应该能够轻松地看到将“p”设置为“a”与将“p指向的内容”设置为“a”非常不同。
此外,由于p应该指向一个char,设置char p指向(当前内存位置为0的“char”,假设null为0)到char指针(a)可能会失败在编译时,如果你很幸运(取决于你的编译器和lint设置,它可能实际上成功。)
来自注释的:在像f(char c)这样的函数声明中,我通常会尝试将变量名与其余部分分开 - 所以它将是f((char )c )。所以c是char *。完全像变量定义。
另外&amp;通常读作“地址”,但这种情况会更加明显。我自己读书的几个例子。可能会或可能不会帮助你。
int a[] = {1,2,3}; // I mentally parse this as (int[]) a, so a is an int array.
int *p; // p is a pointer to "integers"
int i;
p=a; // p acts exactly as a does now.
i=*p; // i is "What is pointed to by" p (1)
i=p; // i is some memory address
i=*a; // i is what is pointed to by a (1)
i=p[1]; // Don't forget that * and [] syntax are generally interchangable.
i=a+1; // Same as above (2).
p=&i; // p is the address of i (it can because it's a pointer)
// remember from hs algebra that = generally reads as "is", still works!
*p=7; // what is pointed to by p (i) is 7;
a=*i; // whoops, can't assign an array. This is the only difference between
// arrays and pointers that you will have to deal with often, so feel
// free to use which ever one you are more comfortable with.
char c='a';
char * d = &c;// d is a char pointer, and it is the address of c
char ** e ; // e is a pointer to a memory location containing
// a pointer to a char!
e=&d; // gets d's address. a pointer to a pointer gets
// the address of a pointer. Messy but gets the job done
**e=5; // what is pointed to by what is pointed to by e is 5.
*e=&'f'; // what is pointed to by e (which is a char * itself, and is still d!)
// is set to the address of the memory location holding the value 'f'.
// does not change c or e, just d!
我在10年内没有接触过c,所以有些可能有点不对劲,但这有助于我大声读出来。
答案 4 :(得分:1)
我认为你错了:
char a[8];
char *p=a;
这是合法的,并且与:
相同char a[8];
char *p=NULL;
p=a;
使用:
char a[8];
char *p=NULL;
*p=a;
正如其他人所说的会产生编译错误或分段错误。
In the left side of declarations you should read *x as pointer(x) while in
statements it must be read as value_pointed_by(x). &x on the other hand
would be pointer_to(x)
答案 5 :(得分:0)
不,它们不等同
如果p = NULL
,那么执行*p = a
会给您一个细分错误。
答案 6 :(得分:0)
我猜他们不一样。