简体   繁体   English

在C中,为什么不能将整数值赋给int *,就像将字符串值赋给char *一样?

[英]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*?

I've been looking through the site but haven't found an answer to this one yet. 我一直在浏览网站,但尚未找到答案。

It is easiest (for me at least) to explain this question with an example. 用一个例子来解释这个问题是最容易的(至少对我来说)。

I don't understand why this is valid: 我不明白为什么这是有效的:

#include <stdio.h>

int main(int argc, char* argv[])
{
  char *mystr = "hello";
}

But this produces a compiler warning ("initialization makes pointer from integer without a cast"): 但是这会产生一个编译器警告(“初始化使整数从没有强制转换的整数中生成”):

#include <stdio.h>

int main(int argc, char* argv[])
{
  int *myint = 5;
}

My understanding of the first program is that creates a variable called mystr of type pointer-to-char, the value of which is the address of the first char ('h') of the string literal "hello". 我对第一个程序的理解是创建一个名为mystr的变量,类型为pointer-to-char,其值是字符串文字“hello”的第一个字符('h')的地址。 In other words with this initialization you not only get the pointer, but also define the object ("hello" in this case) which the pointer points to. 换句话说,使用此初始化,您不仅可以获取指针,还可以定义指针指向的对象(在本例中为“hello”)。

Why, then, does int *myint = 5; 那么,为什么int *myint = 5; seemingly not achieve something analogous to this, ie create a variable called myint of type pointer-to-int, the value of which is the address of the value '5'? 看似没有实现与此类似的东西,即创建一个名为myint的变量,类型指针指向int,其值是值'5'的地址? Why doesn't this initialization both give me the pointer and also define the object which the pointer points to? 为什么这个初始化既不给我指针也定义指针所指向的对象?

In fact, you can do so using a compound literal , a feature added to the language by the 1999 ISO C standard. 实际上,您可以使用复合文字来实现,这是1999 ISO C标准添加到该语言中的一项功能。

A string literal is of type char[N] , where N is the length of the string plus 1. Like any array expression, it's implicitly converted , in most but not all contexts, to a pointer to the array's first element. 字符串文字的类型为char[N] ,其中N是字符串的长度加1.与任何数组表达式一样,它在大多数但不是所有上下文中都隐式转换为指向数组第一个元素的指针。 So this: 所以这:

char *mystr = "hello";

assigns to the pointer mystr the address of the initial element of an array whose contents are "hello" (followed by a terminating '\\0' null character). 为指针mystr分配内容为"hello"的数组的初始元素的地址(后跟终止'\\0' mystr字符)。 Incidentally, it's safer to write: 顺便说一句,写起来更安全:

const char *mystr = "hello";

There are no such implicit conversions for integers -- but you can do this: 整数没有这种隐式转换 - 但你可以这样做:

int *ptr = &(int){42};

(int){42} is a compound literal, which creates an anonymous int object initialized to 42 ; (int){42}是复合文字,它创建一个初始化为42的匿名int对象; & takes the address of that object. &获取该对象的地址。

But be careful: The array created by a string literal always has static storage duration, but the object created by a compound literal can have either static or automatic storage duration, depending on where it appears. 但要小心:由字符串文字创建的数组始终具有静态存储持续时间,但复合文字创建的对象可以具有静态或自动存储持续时间,具体取决于它出现的位置。 That means that if the value of ptr is returned from a function, the object with the value 42 will cease to exist while the pointer still points to it. 这意味着如果从函数返回ptr的值,则指针仍指向它时,具有值42的对象将不再存在。

As for: 至于:

int *myint = 5;

that attempts to assign the value 5 to an object of type int* . 尝试将值5分配给int*类型的对象。 (Strictly speaking it's an initialization rather than an assignment, but the effect is the same). (严格来说,这是初始化而不是赋值,但效果是一样的)。 Since there's no implicit conversion from int to int* (other than the special case of 0 being treated as a null pointer constant), this is invalid. 由于没有从intint*隐式转换(除了0的特殊情况被视为空指针常量),这是无效的。

When you do char* mystr = "foo"; 当你做char* mystr = "foo"; , the compiler will create the string "foo" in a special read-only portion of your executable, and effectively rewrite the statement as char* mystr = address_of_that_string; ,编译器将在可执行文件的特殊只读部分中创建字符串"foo" ,并有效地将语句重写为char* mystr = address_of_that_string;

The same is not implemented for any other type, including integers. 对于任何其他类型,包括整数,都没有实现相同的功能。 int* myint = 5; will set myint to point to address 5 . myint设置为指向地址5

i'll split my answer to two parts: 我将我的答案分成两部分:

1st, why char* str = "hello"; 1,为什么char* str = "hello"; is valid: 已验证:

char* str declare a space for a pointer (number that represents a memory address on the current architecture) char* str为指针声明一个空格(表示当前体系结构上的内存地址的数字)

when you write "hello" you actually fill the stack with 6 bytes of data 当你写"hello"你实际上用6个字节的数据填充堆栈
(don't forget the null termination) lets say at address 0x1000 - 0x1005 . (不要忘记空终止)让我们说地址0x1000 - 0x1005

str="hello" assigns the start address of that 5 bytes (0x1000) to the *str str="hello"将该5个字节(0x1000)的起始地址分配给*str

so what we have is : 所以我们拥有的是:
1. str , which takes 4 bytes in memory, holds the number 0x1000 (points to the first char only!) 1. str ,在内存中占用4个字节 ,保存数字0x1000 (仅指向第一个字符!)
2. 6 bytes 'h' 'e' 'l' 'l' 'o' '\\0' 2. 6字节 'h''e'''''''''''0'

2st, why int* ptr = 0x105A4DD9; 2,为什么int* ptr = 0x105A4DD9; isn't valid: 无效:

well, this is not entirely true! 好吧,这不完全正确!
as said before, a Pointer is a number that represent an address, 如前所述,指针是一个代表地址的数字,
so why cant i assign that number ? 那么为什么我不能分配这个号码?

it is not common because mostly you extract addresses of data and not enter the address manually. 它并不常见,因为大多数情况下您提取数据地址而不是手动输入地址。
but you can if you need !!! 但你可以,如果你需要! ... ...
because it isn't something that is commonly done, 因为它不是常见的东西,
the compiler want to make sure you do so in propose, and not by mistake and forces you to CAST your data as 编译器希望确保您在建议中这样做,而不是错误地强制您将数据作为CAST
int* ptr = (int*)0x105A4DD9;
(used mostly for Memory mapped hardware resources) (主要用于内存映射的硬件资源)

Hope this clear things out. 希望这清楚的事情。
Cheers 干杯

"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*?" “在C中,为什么不能将整数值赋给int *,就像将字符串值赋给char *一样?”

Because it's not even a similar situation, let alone "the same way". 因为它甚至不是类似的情况,更不用说“同样的方式”。

A string literal is an array of char s which – being an array – can be implicitly converted to a pointer to its first element. 字符串文字是一个char数组,它是一个数组 - 可以隐式转换为指向其第一个元素的指针。 Said pointer is a char * . 所述指针是char *

But an int is not either a pointer in itself, nor an array, nor anything else implicitly convertible to a pointer. 但是int既不是指针本身,也不是数组,也不是任何其他隐式可转换为指针的东西。 These two scenarios just don't have anything in common. 这两种情况没有任何共同之处。

The problem is that you are trying to assign the address 5 to the pointer. 问题是您正在尝试将地址5分配给指针。 Here you are not dereferencing the pointer, you are declaring it as a pointer and initializing it to the value 5 (as an address which surely is not what you intend to do). 在这里你没有取消引用指针,你将它声明为指针并将其初始化为值5(作为一个肯定不是你打算做的地址)。 You could do the following. 您可以执行以下操作。

#include <stdio.h>

int main(int argc, char* argv[])
{
  int *myint, b;
  b = 5;
  myint = &b;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM