在 C 中,为什么不能像将字符串值分配给 char* 一样将整数值分配给 int*?
In C, why can't an integer value be assigned to an int* the same way a string value can be assigned to a char*?
我一直在浏览网站,但还没有找到这个问题的答案。
用一个例子来解释这个问题是最简单的(至少对我而言)。
我不明白为什么这是有效的:
#include <stdio.h>
int main(int argc, char* argv[])
{
char *mystr = "hello";
}
但这会产生编译器警告 ("initialization makes pointer from integer without a cast"):
#include <stdio.h>
int main(int argc, char* argv[])
{
int *myint = 5;
}
我对第一个程序的理解是,创建一个名为mystr的变量,类型为pointer-to-char,其值是字符串字面量的第一个字符('h')的地址"hello"。换句话说,通过此初始化,您不仅可以获取指针,还可以定义指针指向的对象(在本例中为 "hello")。
那么,为什么 int *myint = 5;
似乎没有实现与此类似的东西,即创建一个名为 myint 的指针类型变量,其值是值“5”的地址?为什么这个初始化既不给我指针又定义指针指向的对象?
问题是您正试图将地址 5 分配给指针。在这里,您没有取消引用指针,而是将其声明为指针并将其初始化为值 5(作为地址,这肯定不是您打算做的)。您可以执行以下操作。
#include <stdio.h>
int main(int argc, char* argv[])
{
int *myint, b;
b = 5;
myint = &b;
}
当您执行 char* mystr = "foo";
时,编译器将在您的可执行文件的特殊只读部分创建字符串 "foo"
,并有效地将语句重写为 char* mystr = address_of_that_string;
任何其他类型(包括整数)都没有实现相同的方法。 int* myint = 5;
将设置 myint
指向地址 5
。
事实上,您可以使用 复合文字,这是 1999 年 ISO C 标准添加到语言中的一项功能。
字符串文字的类型为 char[N]
,其中 N
是字符串的长度加 1。与任何数组表达式一样,它隐式 converted ,在大多数但不是所有情况下,指向数组第一个元素的指针。所以这个:
char *mystr = "hello";
向指针 mystr
分配内容为 "hello"
的数组的初始元素的地址(后跟终止 '[=18=]'
空字符)。
顺便说一下,这样写更安全:
const char *mystr = "hello";
整数没有这样的隐式转换——但您可以这样做:
int *ptr = &(int){42};
(int){42}
是一个复合字面量,它创建一个初始化为 42
的匿名 int
对象; &
获取该对象的地址。
但要注意:由字符串文字创建的数组始终具有静态存储持续时间,但由复合文字创建的对象可以具有静态或自动存储持续时间,具体取决于它出现的位置。这意味着如果从函数返回 ptr
的值,则具有值 42
的对象将不复存在,而指针仍指向它。
至于:
int *myint = 5;
尝试将值 5
分配给类型 int*
的对象。 (严格来说是初始化而不是赋值,但是效果是一样的)。由于没有从 int
到 int*
的隐式转换(除了 0
被视为空指针常量的特殊情况),这是无效的。
我会将我的回答分为两部分:
1、为什么char* str = "hello";
有效:
char* str
为指针声明一个space(代表当前架构上的内存地址的数字)
当你写 "hello"
时,你实际上用 6 个字节的数据填充了堆栈
(不要忘记空终止)让地址 0x1000 - 0x1005
.
str="hello"
将那 5 个字节 (0x1000) 的起始地址分配给 *str
所以我们拥有的是:
1. str
,在内存中占用 4 个字节,保存数字 0x1000
(仅指向第一个字符!)
2. 6字节 'h' 'e' 'l' 'l' 'o' '\0'
2、为什么 int* ptr = 0x105A4DD9;
无效:
嗯,这不完全正确!
如前所述,指针是代表地址的数字,
所以 为什么我不能分配那个号码?
这并不常见,因为大多数情况下您提取数据地址而不是手动输入地址。
但如果你需要,你可以!!!...
因为这不是通常做的事情,
编译器希望确保您在提议时这样做,而不是错误地强制您将数据转换为
int* ptr = (int*)0x105A4DD9;
(主要用于内存映射硬件资源)
希望这一切都清楚。
干杯
"In C, why can't an integer value be assigned to an int* the same way a string value can be assigned to a char*?"
因为连类似的情况都没有,更不用说"the same way"了。
字符串文字是 char
的数组,作为数组,它可以隐式转换为指向其第一个元素的指针。所说的指针是一个char *
.
但是 int
本身既不是指针,也不是数组,也不是任何其他可隐式转换为指针的对象。这两种情况只是没有任何共同点。
我一直在浏览网站,但还没有找到这个问题的答案。
用一个例子来解释这个问题是最简单的(至少对我而言)。
我不明白为什么这是有效的:
#include <stdio.h>
int main(int argc, char* argv[])
{
char *mystr = "hello";
}
但这会产生编译器警告 ("initialization makes pointer from integer without a cast"):
#include <stdio.h>
int main(int argc, char* argv[])
{
int *myint = 5;
}
我对第一个程序的理解是,创建一个名为mystr的变量,类型为pointer-to-char,其值是字符串字面量的第一个字符('h')的地址"hello"。换句话说,通过此初始化,您不仅可以获取指针,还可以定义指针指向的对象(在本例中为 "hello")。
那么,为什么 int *myint = 5;
似乎没有实现与此类似的东西,即创建一个名为 myint 的指针类型变量,其值是值“5”的地址?为什么这个初始化既不给我指针又定义指针指向的对象?
问题是您正试图将地址 5 分配给指针。在这里,您没有取消引用指针,而是将其声明为指针并将其初始化为值 5(作为地址,这肯定不是您打算做的)。您可以执行以下操作。
#include <stdio.h>
int main(int argc, char* argv[])
{
int *myint, b;
b = 5;
myint = &b;
}
当您执行 char* mystr = "foo";
时,编译器将在您的可执行文件的特殊只读部分创建字符串 "foo"
,并有效地将语句重写为 char* mystr = address_of_that_string;
任何其他类型(包括整数)都没有实现相同的方法。 int* myint = 5;
将设置 myint
指向地址 5
。
事实上,您可以使用 复合文字,这是 1999 年 ISO C 标准添加到语言中的一项功能。
字符串文字的类型为 char[N]
,其中 N
是字符串的长度加 1。与任何数组表达式一样,它隐式 converted ,在大多数但不是所有情况下,指向数组第一个元素的指针。所以这个:
char *mystr = "hello";
向指针 mystr
分配内容为 "hello"
的数组的初始元素的地址(后跟终止 '[=18=]'
空字符)。
顺便说一下,这样写更安全:
const char *mystr = "hello";
整数没有这样的隐式转换——但您可以这样做:
int *ptr = &(int){42};
(int){42}
是一个复合字面量,它创建一个初始化为 42
的匿名 int
对象; &
获取该对象的地址。
但要注意:由字符串文字创建的数组始终具有静态存储持续时间,但由复合文字创建的对象可以具有静态或自动存储持续时间,具体取决于它出现的位置。这意味着如果从函数返回 ptr
的值,则具有值 42
的对象将不复存在,而指针仍指向它。
至于:
int *myint = 5;
尝试将值 5
分配给类型 int*
的对象。 (严格来说是初始化而不是赋值,但是效果是一样的)。由于没有从 int
到 int*
的隐式转换(除了 0
被视为空指针常量的特殊情况),这是无效的。
我会将我的回答分为两部分:
1、为什么char* str = "hello";
有效:
char* str
为指针声明一个space(代表当前架构上的内存地址的数字)
当你写 "hello"
时,你实际上用 6 个字节的数据填充了堆栈
(不要忘记空终止)让地址 0x1000 - 0x1005
.
str="hello"
将那 5 个字节 (0x1000) 的起始地址分配给 *str
所以我们拥有的是:
1. str
,在内存中占用 4 个字节,保存数字 0x1000
(仅指向第一个字符!)
2. 6字节 'h' 'e' 'l' 'l' 'o' '\0'
2、为什么 int* ptr = 0x105A4DD9;
无效:
嗯,这不完全正确!
如前所述,指针是代表地址的数字,
所以 为什么我不能分配那个号码?
这并不常见,因为大多数情况下您提取数据地址而不是手动输入地址。
但如果你需要,你可以!!!...
因为这不是通常做的事情,
编译器希望确保您在提议时这样做,而不是错误地强制您将数据转换为
int* ptr = (int*)0x105A4DD9;
(主要用于内存映射硬件资源)
希望这一切都清楚。
干杯
"In C, why can't an integer value be assigned to an int* the same way a string value can be assigned to a char*?"
因为连类似的情况都没有,更不用说"the same way"了。
字符串文字是 char
的数组,作为数组,它可以隐式转换为指向其第一个元素的指针。所说的指针是一个char *
.
但是 int
本身既不是指针,也不是数组,也不是任何其他可隐式转换为指针的对象。这两种情况只是没有任何共同点。