C语言 为什么改变指针的类型是不正确的?

u91tlkcl  于 2023-11-16  发布在  其他
关注(0)|答案(2)|浏览(132)

我一直在努力理解为什么改变指针的类型是无效的。我在一些地方问过改变类型是无效的,所以我测试了一些代码:
第一个代码:

int *x;
    int y = 35;
    
    x = &y;
    
    printf("%c\n", *x);

字符串
第二个代码:

char *x;
    int y = 35;
    
    x = &y;
    
    printf("%c\n", *x);


我得到的代码告诉我不要改变指针类型:
第三个代码:

void* vp = malloc(100); 

    cp = (char*)vp;          
    for (; *cp != '\0'; cp++) 
    {
        printf("%c", *cp);
    }
    printf("\n\n");

    numbytes = (sizeof(numbers) / sizeof(numbers[0])) * sizeof(int);
    memcpy(vp, numbers, numbytes); 
    ip = (int*)vp;         
    for (; *ip != -1; ip++)
    {
        printf("%d, ", *ip);
    }
    printf("\n\n");

    printf("vp = %p\n", vp);
    
}


我的实际问题是,我被告知不改变指针的类型。而在第三个例子中,它被改变了2次,从void到char到int。在我的第一个和第二个例子中,我也改变了类型,但它是无效的。我不知道为什么。在第三个例子中,它加载了一些值,然后改变了指针的类型。在我的第一个和第二个我也加载了值,并将指针从int改为float。但它是无效的。
什么时候可以改变类型,什么时候不能?我知道int指针可以指向char,但是例如int* x = &(char)y;使用 *x总是返回int值,但是键入(printf(“%c”,x))将返回一个字符,就好像它忽略了指针的类型:>
我什么时候可以换类型?
这里是另一个第四个例子,我把int
指针变成了一个浮点数,其中已经包含了int值,结果是浮点数总是0。

int *x;
int y = 5;
x = &y;

printf("%f\n", *(float*)x);


我试着理解什么时候可以改变指针的类型,什么时候不能。由于malloc类型和指针后面的类型(如int x =(float)y)没有太大关系,这里y旁边的float也没有太大关系,因为算术是基于“x”类型的。虽然它可能会影响结果 *x将显示,因为float有不同的字节分配。
除此之外,我对“类型”什么时候重要以及当它包含值时什么时候可以更改它感到困惑。

s6fujrry

s6fujrry1#

给予这个机会.
第一个月(以及calloc()realloc())将,如果没有问题,“咬掉”一块足够大的 * 堆存储 * 来存储所请求的字节,并对齐以存储语言的最大数据类型(类似于8字节的double)。分配例程被要求提供一定数量的字节,并返回void *,以便程序按照自己的意愿使用这些字节。
C语言允许将void指针(一个地址)转换为指向任何其他数据类型的指针(不严格地说),因此malloc()返回void *
调用函数(通常)将该指针存储到指针变量中,该指针变量的类型满足函数的需要。例如:int *ptrInt = malloc( 10 * sizeof *ptrInt );分配空间以存储10个整数值。这一点你明白。你可以在10个整数的沙箱中玩得尽可能多,然后free( ptrInt );
所有的数据库都是字节的集合。char是一个字节,double是8个字节。对齐和解释是至关重要的!如果你想探索,你可以 * 重新解释 * 一个地址:

double dbl = 3.14159;
unsigned char *ptr = (unsigned char *)&dbl; // Casting to "wrong" type...
for( int i = 0; i < sizeof dbl; i++ )
    printf( "%02x ", ptr[i] );

字符串
这类东西在错误的人手中充满了危险(比如没有经验的程序员)。通过 * 强制转换 * 到错误的类型,编译器提供的保护(警告,错误)被抑制了。程序员已经承担了责任,并将承担任何后果(比如超出声明为受程序代码控制的内存范围)。
一种好的类型转换是用来避免令人讨厌的意外(比如当signed char作为函数的参数提升为int时,它被 * 符号扩展 *)。

char ch = toupper( (unsigned char)0xF7 ); // pass as 0x00F7, not 0xFFF7!


一般来说,苹果就是苹果,橘子就是橘子,直到你对数据在语言(和内存)中的表示方式有了足够的理解,坚持简单的东西,不要不恰当地使用类型转换。
编译器是你的朋友,它希望你写出好的代码来供它咀嚼。像对待其他朋友一样注意它的警告。当你学会理解它的批评并纠正代码中的批评时,你将是受益者!

t98cgbkg

t98cgbkg2#

通过其他类型指针调用未定义的行为,因为它违反了严格的alising规则,除了:
1.当您通过指向相同或兼容类型的指针访问对象时,
1.当你使用指向char的指针访问一个对象时
1.当你用一个空指针分配一个指针,

  • void指针引用具有兼容类型的对象
  • void指针持有对malloc家族函数分配的对象的引用。
  • 片段1是正确的
  • 片段2正确
  • 代码片段3不清楚,因为您没有显示numbers的定义。如果它是int数组,则它是正确的
  • 最后一个代码无效,因为您使用指向float的指针访问int对象

相关问题