我一直在写像
这样的东西char *x=NULL;
假设
char *x=2;
将创建一个指向地址2的char
指针。
但是,在The GNU C Programming Tutorial中,int *my_int_ptr = 2;
表示2
将整数值my_int_ptr
存储到char *x=NULL
中分配的随机地址。
这似乎意味着我自己的NULL
正在将char
强制转换为#include <stdlib.h>
#include <stdio.h>
int main()
{
char *x=NULL;
if (x==NULL)
printf("is NULL\n");
return EXIT_SUCCESS;
}
的值分配给内存中的某个随机地址。
虽然
char *x;
x=NULL;
事实上,确实打印
是NULL
当我编译并运行它时,我担心我依赖于未定义的行为,或者至少是指定不足的行为,我应该写
// The admin requires some twig functions defined in the security
// bundle, like is_granted. Register this bundle if it wasn't the case
// already.
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
// These are the other bundles the SonataAdminBundle relies on
new Sonata\CoreBundle\SonataCoreBundle(),
new Sonata\BlockBundle\SonataBlockBundle(),
new Knp\Bundle\MenuBundle\KnpMenuBundle(),
// And finally, the storage and SonataAdminBundle
new Sonata\DoctrineORMAdminBundle\SonataDoctrineORMAdminBundle(),
new Sonata\AdminBundle\SonataAdminBundle(),
代替。
答案 0 :(得分:110)
是否可以将C指针初始化为NULL?
TL; DR 非常好。
The actual claim made on the guide reads like
另一方面,如果仅使用单个初始赋值
int *my_int_ptr = 2;
,程序将尝试填充my_int_ptr
指向的内存位置的内容,值为2由于my_int_ptr
充满了垃圾,它可以是任何地址。 [...]
嗯,他们 错了,你是对的。
对于语句,(忽略,现在指向整数转换的指针是一个实现定义的行为)
int * my_int_ptr = 2;
my_int_ptr
是一个变量(指向int
的类型指针),它有一个自己的地址(类型:指向整数的指针的地址),你存储的值为{{1}进入那个地址。
现在,2
,作为指针类型,我们可以说,指向 指向的内存位置的“type”值价值保持在my_int_ptr
。因此,您实际上是指定 of 指针变量,而不是指针所指向的内存位置的值。
所以,结论
my_int_ptr
将指针变量 char *x=NULL;
初始化为x
,而不是指针指向的内存地址的值。
与
相同NULL
现在,严格遵守,像
这样的陈述 char *x;
x = NULL;
是非法的,因为它涉及约束违规。要清楚,
int * my_int_ptr = 2;
是指针变量,类型为my_int_ptr
int *
根据定义具有类型2
。并且它们不是“兼容”类型,因此这种初始化是无效的,因为它违反了Lundin's answer中描述的章节§6.5.16.1/ P1中提到的简单赋值规则。
如果有人对初始化与简单赋值约束的关联感兴趣,引用int
,章节§6.7.9,P11
标量的初始值设定项应为单个表达式,可选择用大括号括起来。该 对象的初始值是表达式的初始值(转换后); 相同的类型 适用于简单赋值的约束和转换,采用标量的类型 成为其声明类型的非限定版本。
答案 1 :(得分:53)
教程错了。在ISO C中,int *my_int_ptr = 2;
是一个错误。在GNU C中,它与int *my_int_ptr = (int *)2;
相同。这会将整数2
转换为内存地址,以编译器确定的某种方式。
它不会尝试在该地址所寻址的位置存储任何内容(如果有的话)。如果您继续撰写*my_int_ptr = 5;
,那么它会尝试将号码5
存储在该地址所针对的位置。
答案 2 :(得分:17)
为了澄清教程错误的原因,int *my_int_ptr = 2;
是一个“约束违规”,它是不允许编译的代码,编译器必须在遇到它时给你一个诊断。
根据6.5.16.1简单分配:
约束
以下其中一项应成立:
- 左操作数具有原子,限定或非限定算术类型,右边有算术类型;
- 左操作数具有与右侧类型兼容的结构或联合类型的原子,限定或非限定版本;
- 左操作数具有原子,限定或非限定指针类型,并且(考虑左值操作数在左值后的类型) 转换)两个操作数都是限定或不合格的指针 兼容类型的版本,以及左侧指向的类型 右边所指出的所有限定词;
- 左操作数具有原子,限定或非限定指针类型,并且(考虑左值操作数在左值后的类型) 转换)一个操作数是指向对象类型的指针,另一个是 是一个指向有资格或不合格的void版本的指针 左边指向的类型具有指向的所有类型的限定符 在右边;
- 左操作数是原子,限定或非限定指针,右边是空指针常量;或
- 左操作数的类型为atomic,qualified或nonqualified _Bool,右边是指针。
在这种情况下,左操作数是一个非限定指针。它没有提到右操作数被允许为整数(算术类型)。所以代码违反了C标准。
除非您明确告诉GCC是标准C编译器,否则GCC会表现不佳。如果您将代码编译为-std=c11 -pedantic-errors
,它将正确地提供必要的诊断。
答案 3 :(得分:15)
int *my_int_ptr = 2
将整数值2存储到my_int_ptr中的任何随机地址。
这是完全错误的。如果这是实际写的,那么请获得更好的书或教程。
int *my_int_ptr = 2
定义一个指向地址2的整数指针。如果您尝试访问地址2
,则很可能会崩溃。
*my_int_ptr = 2
,即行中没有int
,将值2存储到指向的任意随机地址my_int_ptr
。说完这个之后,您可以在定义时将NULL
指定给指针。 char *x=NULL;
完全有效C.
编辑:在写这篇文章时我不知道指针转换的整数是实现定义的行为。请查看@ M.M和@SouravGhosh的详细答案。
答案 4 :(得分:14)
关于C指针的许多混淆来自于最初针对编码风格做出的非常糟糕的选择,并且通过语言语法中的一个非常糟糕的小选择得到了证实。
int *x = NULL;
是正确的C,但这是非常误导,我甚至会说荒谬,并且它阻碍了许多新手对语言的理解。这让人觉得以后我们可以做*x = NULL;
,这当然是不可能的。您可以看到,变量的类型不是int
,变量的名称不是*x
,声明中的*
也不会与{合作}发挥任何功能作用{1}}。这纯粹是陈述性的。因此,更有意义的是:
=
这也是正确的C,尽管它不符合原始的K&amp; R编码风格。它非常清楚地表明类型是int* x = NULL;
,并且指针变量是int*
,所以即使对于没有经验的人来说,值x
被存储到{{1}中也很明显。 },这是指向NULL
的指针。
此外,它更容易派生规则:当星星远离变量名称时,它就是一个声明,而附加到名称的星号是指针解除引用。
所以,现在变得更容易理解的是,我们可以进一步向x
或int
进行操作,换句话说,它让新手更容易看到x = NULL;
如何导致*x = 2;
和variable = expression
。 (对于发起的,表达方式&#39;我的意思是&#39; rvalue&#39;。)
语言语法中的不幸选择是,在声明局部变量时,您可以说pointer-type variable = pointer-expression
声明一个整数和指向整数的指针,因此它会让人相信dereferenced-pointer-variable = expression
是名称的有用部分。但事实并非如此,这种语法只是一个古怪的特殊情况,为方便起见而添加,在我看来它应该从未存在过,因为它使我上面提出的规则无效。据我所知,语言中没有其他地方是这种语法有意义,但即使它是,它指的是指针类型在C中定义的方式的差异。在其他地方,在单变量声明中,在参数列表中,在struct members等中,您可以将指针声明为int i, *p;
而不是*
;它是完全合法的,更有意义。
答案 5 :(得分:6)
我想补充一些与许多优秀答案正交的东西。实际上,初始化为NULL
远非不好的做法,如果该指针可能会或可能不会用于存储动态分配的内存块,则可能很方便。
int * p = NULL;
...
if (...) {
p = (int*) malloc(...);
...
}
...
free(p);
由于根据ISO-IEC 9899 standard free
在参数为NULL
时是一个nop,上面的代码(或者在同一行中更有意义的东西)是合法的。
答案 6 :(得分:1)
这是一个空指针
int * nullPtr = (void*) 0;
答案 7 :(得分:1)
这是正确的。
int main()
{
char * x = NULL;
if (x==NULL)
printf("is NULL\n");
return EXIT_SUCCESS;
}
此功能对于它的功能是正确的。它将地址0指定给char指针x。也就是说,它将指针x指向存储器地址0。
替代:
int main()
{
char* x = 0;
if ( !x )
printf(" x points to NULL\n");
return EXIT_SUCCESS;
}
我猜你想要的是:
int main()
{
char* x = NULL;
x = alloc( sizeof( char ));
*x = '2';
if ( *x == '2' )
printf(" x points to an address/location that contains a '2' \n");
return EXIT_SUCCESS;
}
x is the street address of a house. *x examines the contents of that house.
答案 8 :(得分:-2)
请记住:
在C中,左侧值始终计算到内存位置,而右侧始终计算为值(无论是int还是地址或类Foo)。