最冤枉的关键字-sizeof
- 格式:doc
- 大小:22.50 KB
- 文档页数:2
c语言容易造成内存越界的函数在C语言编程中,内存管理是一个非常重要的话题,而内存越界错误则是一个常见的bug类型。
内存越界是指程序访问了超出其所分配内存空间范围的内存地址,这可能会导致程序崩溃、数据损坏甚至是安全漏洞。
在C语言中,有一些函数容易造成内存越界错误,下面将介绍一些常见的这类函数:1. **strcpy函数**:strcpy函数用于将一个字符串复制到另一个字符串中,但是它并不会检查目标字符串是否有足够的空间来存放源字符串,如果目标字符串长度小于源字符串长度,就会造成内存越界错误。
2. **strcat函数**:strcat函数用于将一个字符串追加到另一个字符串的末尾,同样也不会检查目标字符串的空间是否足够。
如果目标字符串的空间不足,就会造成内存越界错误。
3. **gets函数**:gets函数用于从标准输入读取字符串,但是它并不会限制字符串的长度,如果输入的字符串长度超过目标数组的大小,就会造成内存越界错误。
4. **sprintf函数**:sprintf函数用于将格式化的数据写入字符串,如果格式化的数据长度超过目标字符串的长度,就会造成内存越界错误。
5. **scanf函数**:scanf函数用于从标准输入读取格式化的数据,如果输入的数据类型和目标变量的类型不匹配,就会造成内存越界错误。
为了避免内存越界错误,我们可以采取一些措施,比如使用安全的函数来替代容易造成内存越界错误的函数,比如使用strncpy函数替代strcpy函数,使用strncat函数替代strcat函数,使用fgets函数替代gets函数,使用snprintf函数替代sprintf函数。
另外,还可以使用动态内存分配函数来动态分配内存,比如malloc函数、calloc函数和realloc函数,来避免静态内存分配的内存越界错误。
总的来说,内存越界错误是C语言编程中常见的bug类型,我们需要谨慎地使用函数,避免造成内存越界错误,以确保程序的稳定性和安全性。
对C语言中的sizeof的介绍分析对C语言中的sizeof的介绍分析引导语::sizeof是C语言中判断数据类型或者表达式长度符,以下是店铺分享给大家的对C语言中的sizeof的介绍分析,欢迎阅读!1.定义sizeof是C/C++中的一个操作符(operator),作用就是返回一个对象或者类型所占的内存字节数。
返回值类型为size_t,在头文件stddef.h中定义。
这是一个依赖于编译系统的值,一般定义为typedef unsigned int size_t;编译器林林总总,但作为一个规范,都会保证char、signed char和unsigned char的sizeof值为1,毕竟char是编程能用的最小数据类型。
MSDN上的解释为:The sizeof keyword gives the amount of storage, in bytes, associated with avariable or atype (including aggregate types). This keyword returns a value of typesize_t.2. 语法:sizeof有三种语法形式,如下:1) sizeof( object ); // sizeof( 对象 );2) sizeof( type_name ); // sizeof( 类型 );3) sizeof object; // sizeof 对象;所以一下三种sizeof的使用都是对的复制代码代码如下:#includemain(){int b;printf("%dn",sizeof b);printf("%dn",sizeof(b));printf("%dn",sizeof(int));}3. 基本数据类型的sizeof这里的基本数据类型指short、int、long、float、double这样的简单内置数据类型,由于它们都是和系统相关的,所以在不同的系统下取值可能不同,这务必引起我们的注意,尽量不要在这方面给自己程序的移植造成麻烦。
数组结束符sizeof数组是一种在编程中经常使用的数据结构,它由一系列相同类型的元素组成。
在C语言中,数组的大小通常通过数组的元素个数乘以每个元素占用的字节数来确定。
而在计算数组的大小时,sizeof运算符则是一个非常有用的工具。
sizeof运算符是C语言中的一个关键字,用于计算某个类型的对象所占用的字节数。
在使用sizeof运算符时,可以用它来计算数组的大小。
在C语言中,数组的大小是由数组的元素个数乘以每个元素所占用的字节数得到的。
在计算数组的大小时,sizeof运算符的使用方法是在sizeof后面加上数组名,并用括号括起来。
例如,如果有一个int类型的数组arr,那么可以使用sizeof(arr)来计算数组arr的大小。
sizeof运算符的返回值的类型是size_t,这是一种无符号整数类型。
它的大小足够大,可以表示任何对象的大小。
在实际编程中,可以使用%zu格式化字符来输出size_t类型的值。
需要注意的是,sizeof运算符计算的是整个数组所占用的内存空间的大小,并不仅仅是数组元素的个数。
在计算数组的大小时,sizeof运算符会将数组的元素个数乘以每个元素所占用的字节数,并返回结果。
使用sizeof运算符计算数组的大小具有以下几个优点:1. 精确:sizeof运算符能够准确地计算数组的大小,不会出现计算错误的情况。
这对于编写安全可靠的程序非常重要。
2. 灵活:sizeof运算符可以用于任何类型的数组,无论是基本类型还是自定义类型。
不同类型的数组可以使用同样的方式来计算大小。
3. 方便:sizeof运算符的使用非常简单,只需要在sizeof后面加上数组名,并用括号括起来即可。
不需要复杂的计算过程和额外的代码。
除了计算数组的大小之外,sizeof运算符还可以用于计算其他类型的对象的大小。
例如,可以使用sizeof运算符来计算结构体、联合体、指针等类型的对象所占用的字节数。
需要注意的是,在使用sizeof运算符计算指针类型的对象时,sizeof运算符实际上计算的是指针本身所占用的字节数,而不是指针指向的对象所占用的字节数。
sizeof()的⽤法1. 定义sizeof 是⼀个操作符 operator,不是⼀个函数,其作⽤是返回⼀个对象或类型所占的内存字节数---------------------------------------------------------------------------------------------------------2. 语法sizeof object; //sizeof 对象sizeof(object);sizeof(type_name); // 例如 sizeof(int)对象 object 可以是各种类型的变量,以及表达式(⼀般sizeof不会对表达式进⾏计算);sizeof对对象求内存⼤⼩,最终都是转化为对对象的数据类型进⾏求值;sizeof(表达式) 值为表达式的最终结果的数据类型的⼤⼩int i;sizeof(int); //值为4sizeof(i); //值为4,等价于sizeof(int)sizeof i; //值为4sizeof(2); //值为4,等价于sizeof(int),因为2的类型为intsizeof(2 + 3.14); //值为8,等价于sizeof(double),因为此表达式的结果的类型为doublechar ary[sizeof(int) * 10]; //OK,编译⽆误---------------------------------------------------------------------------------------------------------3. 基本数据类型的sizeof基本数据类型如int short long char double等,其内存⼤⼩与系统有关。
32位系统的int(4 Bytes), short(2 Bytes), long(4 Bytes), char(1 Bytes), double(8 Bytes), float(4 Bytes)4. 结构体的sizeof结构体的sizeof涉及到字节对齐问题,字节对齐有助于加快计算机的存取速度,减⼩指令周期。
链接脚本(LinkerScript)⽤法解析(⼀)关键字SECTIONS与MEMORY1.MEMORY关键字⽤于描述⼀个MCU ROM和RAM的内存地址分布(Memory Map),MEMORY中所做的内存描述主要⽤于SECTIONS中LMA和VMA的定义。
2.SECTIONS关键字⽤于定义output section(输出段)的相应input section(输⼊段)、LMA和VMA,是整个连接脚本中最为重要的部分。
注:output section 是实际存储在内存中的“段”,⽽input section是其构成成员,如.data为数据段,由所有全局变量构成(默认情况下);.text为代码段,由所有函数构成(默认情况下)...3.下⾯我们⾸先来介绍MEMORY的语法,MEMORY的语法格式如下:MEMORY{ <name> [(<attr>)] : ORIGIN = <origin>, LENGTH = <len> ...}其中<name>是所要定义的内存区域的名字,<origin>是其起始地址,<len>为内存区域的⼤⼩。
另外,<attr>是可选的,并不重要,具体⽤法可参考GNU Linker 的语法说明。
MEMORY的⼀个具体使⽤实例如下:MEMORY{ rom (rx) : ORIGIN = 0, LENGTH = 256K // MEMORY语法中可以使⽤如K、M和G这样的内存单位 ram (!rx) : org = 0x40000000, l = 4M // ORIGIN可以写为org,⽽LENGTH可以写为l}4.在介绍SECTIONS的⽤法之前,我们先对之前提到的LMA和VMA进⾏说明:每个output section都有⼀个LMA和⼀个VMA,LMA是其存储地址,⽽VMA是其运⾏时地址,例如将全局变量g_Data所在数据段.data的LMA设为0x80000020(属于ROM地址),VMA设为0xD0004000(属于RAM地址),那么g_Data的值将存储在ROM中的0x80000020处,⽽程序运⾏时,⽤到g_Data的程序会到RAM中的0xD0004000处寻找它。
一、sizeof的概念sizeof是C语言的一种单目操作符,如C语言的其他操作符++、--等。
它并不是函数。
sizeof操作符以字节形式给出了其操作数的存储大小。
操作数可以是一个表达式或括在括号内的类型名。
操作数的存储大小由操作数的类型决定。
二、sizeof的使用方法1、用于数据类型sizeof使用形式:sizeof(type)数据类型必须用括号括住。
如sizeof(int)。
2、用于变量sizeof使用形式:sizeof(var_name)或sizeof var_name变量名可以不用括号括住。
如sizeof (var_name),sizeof var_name等都是正确形式。
带括号的用法更普遍,大多数程序员采用这种形式。
注意:sizeof操作符不能用于函数类型,不完全类型或位字段。
不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。
如sizeof(max)若此时变量max定义为int max(),sizeof(char_v) 若此时char_v定义为char char_v [MAX]且MAX未知,sizeof(void)都不是正确形式。
三、sizeof的结果sizeof操作符的结果类型是size_t,它在头文件中typedef为unsignedint类型。
该类型保证能容纳实现所建立的最大对象的字节大小。
1、若操作数具有类型char、unsigned char或signed char,其结果等于1。
ANSI C正式规定字符类型为1字节。
2、int、unsigned int 、short int、unsigned short 、long int 、unsigned long 、float、double、long double类型的sizeof 在ANSI C中没有具体规定,大小依赖于实现,一般可能分别为2、2、2、2、4、4、4、8、10。
C语言编程时常犯的17种错误C语言编程时常犯的错误1、书写标识符时,忽略了大小写字母的区别。
main(){ int a=5; printf("%d",A);}编译程序把a和A认为是两个不同的变量名,而显示出错信息。
C认为大写字母和小写字母是两个不同的字符。
习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。
2、忽略了变量的类型,进行了不合法的运算。
代码如下:main(){ float a,b; printf("%d",a%b);}%是求余运算,得到a/b的整余数。
整型变量a和b可以进行求余运算,而实型变量则不允许进行“求余”运算。
3、将字符常量与字符串常量混淆。
char c;c=”a”;在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符,字符串常量是一对双引号括起来的字符序列。
C规定以“\”作字符串结束标志,它是由系统自动加上的,所以字符串“a”实际上包含两个字符:‘a’和‘’,而把它赋给一个字符变量是不行的。
4、忽略了“=”与“==”的区别。
在许多高级语言中,用“=”符号作为关系运算符“等于”。
如在BASIC 程序中可以写if (a=3) then …但C语言中,“=”是赋值运算符,“==”是关系运算符。
如:if (a==3) a=b;前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。
由于习惯问题,初学者往往会犯这样的错误。
5、忘记加分号。
分号是C语句中不可缺少的一部分,语句末尾必须有分号。
a=1b=2编译时,编译程序在“a=1”后面没发现分号,就把下一行“b=2”也作为上一行语句的一部分,这就会出现语法错误。
改错时,有时在被指出有错的一行中未发现错误,就需要看一下上一行是否漏掉了分号。
代码如下:{ z=x+y; t=z/100; printf("%f",t);}对于复合语句来说,最后一个语句中最后的分号不能忽略不写(这是和PASCAL不同的)。
auto 局部变量(自动储存)break无条件退出程序最内层循环case switch语句中选择项char单字节整型数据const定义不可更改的常量值continue中断本次循环,并转向下一次循环default switch语句中的默认选择项do 用于构成do.....while循环语句double定义双精度浮点型数据else构成if.....else选择程序结构enum枚举extern在其它程序模块中说明了全局变量float定义单精度浮点型数据for构成for循环语句goto构成goto转移结构if构成if....else选择结构int基本整型数据long长整型数据registerCPU内部寄存的变量return用于返回函数的返回值short短整型数据signed有符号数sizoef计算表达式或数据类型的占用字节数static定义静态变量struct定义结构类型数据switch构成switch选择结构typedef重新定义数据类型union联合类型数据unsigned定义无符号数据void定义无类型数据volatile该变量在程序中执行中可被隐含地改变while用于构成do...while或while循环结构if( )… else …条件语句switch多分支选择语句for( )…循环语句while( )…循环语句do … while( )循环语句continue结束本次循环语句break终止执行switch 或循环语句return返回语句goto转向语句说明:以上语句中“()”表示一个条件,“…”表示内嵌语句。
goto语句:无条件转向;if语句:和goto语句构成循环语句;while语句;实现"当型"循环;do-while语句:先执行循环体,然后判断循环条件是否成立.for语句:循环,可替代while语句;break语句跳出switch循环continue语句:继续;switch语句:选择;return语句:返回;。
C语言中32个关键字详解由ANSI标准定义的C语言关键字共32个:auto double int struct break else long switchcase enum register typedef char extern return unionconst float short unsigned continue for signed voiddefault goto sizeof volatile do if while static根据关键字的作用,可以将关键字分为数据类型关键字和流程控制关键字两大类。
1数据类型关键字A基本数据类型(5个)void:声明函数无返回值或无参数,声明无类型指针,显式丢弃运算结果char:字符型类型数据,属于整型数据的一种int:整型数据,通常为编译器指定的机器字长float:单精度浮点型数据,属于浮点数据的一种double:双精度浮点型数据,属于浮点数据的一种B类型修饰关键字(4个)short:修饰int,短整型数据,可省略被修饰的int。
long:修饰int,长整形数据,可省略被修饰的int。
signed:修饰整型数据,有符号数据类型unsigned:修饰整型数据,无符号数据类型C复杂类型关键字(5个)struct:结构体声明union:共用体声明enum:枚举声明typedef:声明类型别名sizeof:得到特定类型或特定类型变量的大小D存储级别关键字(6个)auto:指定为自动变量,由编译器自动分配及释放。
通常在栈上分配static:指定为静态变量,分配在静态变量区,修饰函数时,指定函数作用域为文件内部register:指定为寄存器变量,建议编译器将变量存储到寄存器中使用,也可以修饰函数形参,建议编译器通过寄存器而不是堆栈传递参数extern:指定对应变量为外部变量,即在另外的目标文件中定义,可以认为是约定由另外文件声明的韵蟮囊桓觥耙谩?const:与volatile合称“cv特性”,指定变量不可被当前线程/进程改变(但有可能被系统或其他线程/进程改变)volatile:与const合称“cv特性”,指定变量的值有可能会被系统或其他进程/线程改变,强制编译器每次从内存中取得该变量的值2流程控制关键字A跳转结构(4个)return:用在函数体中,返回特定值(或者是void值,即不返回值)continue:结束当前循环,开始下一轮循环break:跳出当前循环或switch结构goto:无条件跳转语句B分支结构(5个)if:条件语句else:条件语句否定分支(与if连用)switch:开关语句(多重分支语句)case:开关语句中的分支标记default:开关语句中的“其他”分治,可选。
1.5,最冤枉的关键字----sizeof
1.5.1,常年被人误认为函数
sizeof 是关键字不是函数,其实就算不知道它是否为32 个关键字之一时,我们也可以借助编译器确定它的身份。
看下面的例子:
int i=0;
A),sizeof(int);B),sizeof(i);C),sizeof int;D),sizeof i;
毫无疑问,32 位系统下A),B)的值为4。
那C)的呢?D)的呢?
在32 位系统下,通过Visual C++6.0 或任意一编译器调试,我们发现D)的结果也为4。
咦?sizeof 后面的括号呢?没有括号居然也行,那想想,函数名后面没有括号行吗?由此轻易得出s izeof 绝非函数。
好,再看C)。
编译器怎么怎么提示出错呢?不是说s izeof 是个关键字,其后面的括号可以没有么?那你想想s izeof int 表示什么啊?int 前面加一个关键字?类型扩展?明显不正确,我们可以在i nt 前加u nsigned,const 等关键字但不能加s izeof。
好,记住:sizeof 在计算变量所占空间大小时,括号可以省略,而计算类型(模子)大小时不能省略。
一般情况下,咱也。
做我的关别偷这个懒,乖乖的写上括号,继续装作一个“函数”,做一个“披着函数皮的关键字”
键字,让人家认为是函数去吧。
1.5.2,sizeof(int)*p 表示什么意思?
sizeof(int)*p 表示什么意思?留几个问题(讲解指针与数组
时会详细讲解),32 位系统下:int *p = NULL;
sizeof(p)的值是多少?
sizeof(*p)呢?
int a[100];
sizeof (a) 的值是多少?
sizeof(a[100])呢?//请尤其注意本
例。
sizeof(&a)呢?
sizeof(&a[0])呢?
int b[100];
void fun(int b[100])
{
sizeof(b);// sizeof (b) 的值是多少?}。