Dev*_*vat 0 c malloc pointers const
#include<stdio.h>
#include<stdlib.h>
int *func(int *);
int main(void)
{
int i,size;
const int *arr=func(&size);
for(i=0;i<size;i++)
{
printf("Enter a[%d] : ",i);
scanf("%d",&arr[i]);
}
for(i=0;i<size;i++)
{
printf("%d\t",arr[i]);
}
return 0;
}
int *func(int *psize)
{
int *p;
printf("Enter the size: ");
scanf("%d",psize);
p=(int *)malloc(*psize *sizeof(int));
return p;
}
Run Code Online (Sandbox Code Playgroud)
输入大小:3
输入[0]:1
输入[1]:2
输入[2]:3
1 2 3
你刚刚遇到很多情况中的一个,C允许你射击你的脚 - 无论好坏.
关于您的假设的一些一般性评论:const是您给编译器的保证.所以你必须确保不违反合同.C没有真正的常数[1].在语义上const是一个限定符`,它允许编译器进行额外的错误检查.但是这需要编译器知道参数的类型.这对于具有适当原型的函数来说是正确的,但是(通常[2])不适用于具有可变数量的参数("可变函数")的函数,因为它们的类型在编译时未给出(并且在运行时未明确提供) -时间).
在
Run Code Online (Sandbox Code Playgroud)scanf("%d",&arr[i]);
您实际上将一个有问题的(见下文)指针类型传递给scanf.函数本身不检查,但只是期望正确的类型.它不能,因为C在运行时不提供对象的类型.
一个现代编译器应该警告参数类型不匹配for printf和scanf.始终启用警告(至少使用gcc -Wall -Wextra -Wconversions)并注意它们.
编辑:经过激烈的讨论,我不得不改变主意.由于最初给出的原因,它似乎不是未定义的行为[3]:传递const int *给scanf期望的a int *.
这是因为在第一次写入(6.5p6)之前,malloced in 对象func没有有效类型.这发生在使用.因此,对象具有类型- 否.但是,您通过a进一步访问是有效的.6.7.3p6仅使另一方向未定义行为(有充分理由).scanfint *intconstconst int *
只有可变函数才能通过未检测到,因为没有关于函数声明中可用的预期类型的信息.像这样的东西:
void f(int *p)
{
*p = 0;
}
int main(void)
{
const int *p = ...;
f(p);
}
Run Code Online (Sandbox Code Playgroud)
这里编译器会生成一个警告.变量函数属于C无法检查限定符正确性的情况(这也包括例如volatile).有更多,有些是非常微妙的.
这里唯一未定义行为的情况是传递一个不兼容的不同限定指针(6.7.6.1p2).
Recomendation:启用警告,但不要依赖编译器检测所有缺陷(不仅仅是const-correctness).如果您需要更加安全,C语言不是正确的语言.有很好的理由存在像Python,Java等高级语言(C++介于两者之间).OTOH在C语言中的开放式结尾允许在需要时在这些语言中很难完成(如果有的话).无论如何:了解你的工具.
注意:你不应该把malloc朋友的结果投在C中.并且sizeof(char)没用.它由产量标准定义1.
[1]由于违反合同是未定义的行为,编译器实际上可以自由地将这些数据存储在只读存储器中.例如,这对于运行代码并直接从ROM读取一些数据的微控制器至关重要.
[2]现代编译器可以解析参数类型的格式字符串printf和字符串,scanf并警告错配.但是,这需要此字符串为字符串文字(不是变量).这是编译器编写的一种礼节,这些功能被广泛使用.
[3]基本上未定义的行为意味着任何事情都可能发生 - 您的计算机可能会逃跑,可能会出现鼻守护进程,或者它可能会起作用.但所有都不能保证可靠或确定性.所以下次你开始其他事情可能会发生.
| 归档时间: |
|
| 查看次数: |
119 次 |
| 最近记录: |