简体   繁体   English

当您键入将整数值转换为char指针时会发生什么?

[英]What happens when you type cast an integer value into a char pointer?

For example, 例如,

char * integerToString(void);

int main() {
    char *myString;
    do {
        myString = integerToString();
    } while (myString == (char *)-1); // worked as intended
    free(myString);
    return 0;
}

char * integerToString(void) {

    int userInput;
    printf("Enter an integer: ");
    scanf("%d", &userInput);

    if (userInput < 0 || userInput > 99)
        return (char *)-1; // what happens here?

    char *myString = (char *)malloc(sizeof(char) * 2);
    myString[0] = (int)floor(userInput/10.0) + '0';
    myString[1] = userInput%10 + '0';
    return myString;
}

and the program worked as intended, but what exactly happens when you type cast an integer value (without assigning the integer to a variable) into a character pointer? 并且该程序按预期工作,但是当您键入将整数值(不将整数分配给变量)时,将其完全转换为字符指针会发生什么? Will this program always work? 这个程序会一直有效吗? Thanks. 谢谢。

C99: C99:

6.3.2.3 Pointers 6.3.2.3指针

  1. An integer constant expression with the value 0, or such an expression cast to type void * , is called a null pointer constant . 值为0的整数常量表达式,或强制类型为void *的表达式,称为空指针常量 If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer , is guaranteed to compare unequal to a pointer to any object or function. 如果将空指针常量转换为指针类型,则保证生成的指针(称为空指针 )可以将不相等的指针与指向任何对象或函数的指针进行比较。

[...] [...]

  1. An integer may be converted to any pointer type. 整数可以转换为任何指针类型。 Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation. 除非先前指定,否则结果是实现定义的,可能未正确对齐,可能未指向引用类型的实体,并且可能是陷阱表示。

So casting -1 to a pointer has implementation-defined results. 因此,将-1强制转换为指针具有实现定义的结果。 Therefore the answer is no: This is not guaranteed to work in general. 因此,答案是否定的:这不能保证总体上可行。


In particular: If it does turn out to be a trap representation, your code runs afoul of: 特别是:如果确实是陷阱表示,则您的代码将与以下内容发生冲突:

6.2.6 Representation of types 6.2.6类型的表示

6.2.6.1 General 6.2.6.1概述

[...] [...]

  1. Certain object representations need not represent a value of the object type. 某些对象表示形式不必表示对象类型的值。 If the stored value of an object has such a representation and is read by an lvalue expression that does not have character type, the behavior is undefined. 如果对象的存储值具有这种表示形式,并且由不具有字符类型的左值表达式读取,则该行为是不确定的。 If such a representation is produced by a side effect that modifies all or any part of the object by an lvalue expression that does not have character type, the behavior is undefined. 如果这样的表示是由副作用产生的,该副作用通过不具有字符类型的左值表达式修改对象的全部或任何部分,则该行为是不确定的。 Such a representation is called a trap representation . 这样的表示称为陷阱表示

Ie while (myString == (char *)-1); while (myString == (char *)-1); has undefined behavior if myString is a trap representation. 如果myString是陷阱表示,则具有未定义的行为。

What happens when you type cast an integer value into a char pointer? 当您键入将整数值转换为char指针时会发生什么?

In general, that is undefined behavior (at least as soon as you dereference it). 通常,这是未定义的行为 (至少在取消引用后立即执行)。 Be very scared . 要非常害怕 Read a lot more about UB (it is a tricky subject). 阅读有关UB的更多信息(这是一个棘手的主题)。

In some documented cases, you can case an uintptr_t or intptr_t integral value into a valid pointer. 在某些记录的情况下,您可以将uintptr_tintptr_t整数值放入有效的指针中。

In your case, your heap allocated string is too short (so you have a buffer overflow , which is one of the many examples of UB). 在您的情况下,您分配给堆的字符串太短(因此,您有一个缓冲区溢出 ,这是UB的许多示例之一)。 You forgot the space for the terminating NUL byte, and you forgot to check against failure of malloc . 您忘记了终止NUL字节的空间,并且忘记了检查malloc失败。 BTW, sizeof(char) is always 1. 顺便说一句, sizeof(char) 始终为 1。

You could code: 您可以编写以下代码:

if (userInput < 0 || userInput > 99)
    return NULL;

char *myString = (char *)malloc(3);
if (!myString) { perror("malloc myString"); exit(EXIT_FAILURE); };
myString[0] = (int)floor(userInput/10.0) + '0';
myString[1] = userInput%10 + '0';
myString[2] = (char)0;
return myString;

On most systems (but not all), (char*)-1 is never a valid address (always outside of the virtual address space ) and can never be given by system (or standard) functions. 在大多数系统(但不是全部)上, (char*)-1永远不是有效地址(总是在虚拟地址空间之外 ),并且永远不能由系统(或标准)功能给出。 On My Linux/x86-64 desktop, I know that (char*)-1 is not a valid address (eg because it is MAP_FAILED ), and I could (sometimes) use that as a sentinel non-null pointer value (which should not be derefenced). 在我的Linux / x86-64桌面上,我知道 (char*)-1不是有效的地址(例如,因为它是MAP_FAILED ),所以我(有时)可以将其用作前哨非空指针值(该值应该不要取消引用)。 But that makes my code less portable . 但这使我的代码不那么可移植

So you could decide and document that your integerToString gives (char*)-1 on non-integer input and NULL on heap allocation failure. 因此,您可以决定并记录您的integerToString在非整数输入上给出(char*)-1 ,而在堆分配失败上给出NULL That would work on my Linux/x86-64 desktop (so I sometimes do that). 那可以在我的Linux / x86-64桌面上工作(所以有时我可以这样做)。 But that is not pure (portable) C11 code. 但这不是纯(便携式)C11代码。

But if you stick to the C11 standard (read n1570 ) it is implementation defined what and if (char*)-1 is meaningful. 但是,如果您坚持使用C11标准(读取n1570 ),则它是实现定义的内容,并且(char*)-1是否有意义。 It might be some trap representation that you are not even allowed to compare (even if I don't know any actual C implementation doing that). 甚至可能是某些陷阱表示形式甚至不允许您进行比较(即使我不知道这样做的实际C实现)。

Actually your example illustrates that people never code for pure standard C11 ; 实际上,您的示例说明人们从来没有为纯标准C11编写代码 they always (and so do I) make additional assumptions on the C implementation; 他们总是(我也是)对C的实现做出其他假设 but you do need to be aware of them , and these assumptions could make the porting of your code to some hypothetical future machine a nightmare. 但是您确实需要意识到它们 ,这些假设可能会使将代码移植到某些假设的未来机器上的噩梦。

Will this program always work? 这个程序会一直有效吗?

This is a too general question. 这是一个太笼统的问题。 Your original program didn't even handle failure of malloc and had a buffer overflow (because you forgot the space for the terminating zero byte). 您的原始程序甚至没有处理malloc失败,并且有缓冲区溢出 (因为您忘记了终止零字节的空间)。 However, sadly for you, it would apparently often seems to work (and that is why UB is so scary). 但是,对您来说可悲的是,它似乎通常似乎可以工作(这就是UB 如此恐怖的原因)。 Consider however this (standard conforming, but non-realistic) malloc implementation as food for thought. 但是, 将此 malloc实现(符合标准但不切实际的)视为malloc深思的。

(explaining exactly why your program appears to behave like you want is really difficult, because you need to dive into several implementation details) (确切解释为什么程序看起来像您想要的那样非常困难,因为您需要深入研究几个实现细节)

This program is an example of improper error handling. 该程序是错误处理错误的一个示例。 The value of (char *)-1 appears to be implementation defined, see the other answers. (char *)-1似乎是实现定义的,请参见其他答案。 Since this address is likely not a valid memory address that would be returned from malloc , this is used as a sentinel value in the program. 由于此地址可能不是从malloc返回的有效内存地址,因此在程序中将其用作标记值 The actual value is not of interest, it is compared to the same expression in the other function. 实际值无关紧要,将其与其他函数中的相同表达式进行比较。

If you run this, malloc just might return whatever value that (char *)-1 evaluates to. 如果运行此命令,则malloc 可能会返回(char *)-1求值的任何值。 Then it will be interpreted as an error, although it is a valid memory address. 尽管它是一个有效的内存地址,但它将被解释为错误。

A better way would be to have an argument to integerToString of type int * and use this as a boolean to indicate failure. 更好的方法是为int *类型的integerToString提供参数, integerToString其用作指示失败的布尔值。 Then one would not reserve one char * value for error handling. 这样一来,就不会为错误处理保留一个char *值。

Or use C++ and an exception. 或使用C ++和一个例外。

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

相关问题 当将整数指针转换为char指针时,实际发生了什么? - What actually happens when a pointer to integer is cast to a pointer to char? 将整数数组转换为char数组时会发生什么 - What happens when you cast an integer array into a char array 当我们将值重新分配给 char 指针时,内存会发生什么? - What happens with memory when we reassign value to char pointer? 当我们进行 (char *) 转换以将 integer 数据存储到 char 指针时会发生什么? - What happens when we do (char *) casting to store integer data into char pointer? 当您传递已经分配的值指针时,会发生什么? - What happens exactly when you pass by value pointer that is already allocated? 当地址不以字对齐时,在C中将char *地址转换为int *时会发生什么? - What happens when you cast a char * address to int * in C when the address is not word-aligned? 如果使char * ptr存储整数变量的地址会怎样? - What happens if you make a char *ptr store address of integer variable 当没有指针指向char指针的记忆时会发生什么? - What happens to the momory of a char pointer when no pointer is being pointed at it? 将 float 指针类型转换为 char 指针时会发生什么? - What happens when float pointer is typecasted to char pointer? 在 C 中将 int 列表转换为 char 列表时会发生什么? - What happens when a int list is cast as a char list in C?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM