深入理解C语言-----各数据类型大小_c语言defined和ndefined-程序员宅基地

技术标签: C/C++  c语言  数据类型  

首先看下C标准中“未明确定义”的三种类型Implementation-defined、Unspecified和Undefined。


Implementation-defined 的情况,是C 标准没有明确规定,但是要求编译器必须对此做出明确规定,并写在编译器的文档中。


Unspecified的情况,往往有几种可选的处理方式,C 标准没有明确规定按哪种方式处理,编译器可以自己决定,并且也不必写在编译器的文档中,这样即使用同一个编译器的不同版本来编译也可能得到不同的结果,因为编译器没有在文档中明确写它会怎么处理,那么不同版本的编译器就可以选择不同的处理方式,比如一个函数调用的各个实参表达式按什么顺序求值是Unspecified的。


Undefined的情况则是完全不确定的,C 标准没规定怎么处理,编译器很可能也没规定,甚至也没做出错处理,有很多Undefined的情况是编译器是检查不出来的,最终会导致运行时错误,比如数组访问越界就是Undefined的。


除了char型在C 标准中明确规定占一个字节之外,其它整数类型占几个字节都是Implementation Defined。通常的编译器实现遵守ILP32 或LP64规范。

LP32 这个缩写的意思是int (I )、long(L )和指针(P )类型都占32位,通常32位计算机的C 编译器采用这种规范,x86 平台的gcc 也是如此。LP64是指long(L )和指针占64位,通常64位计算机的C 编译器采用这种规范。指针类型的长度总是和计算机的位数一致。


(PS下,long long 类型对应的占位符和平台和编译器有关,linux中gcc很统一用%lld,在windows中,MinGW的gcc和VC6都需要用到%I64d,但VS2008却是%lld)

在limit.h文件中有比较详细的定义

/* Copyright (C) 1991, 1992, 1996, 1997, 1998, 1999, 2000, 2005
   Free Software Foundation, Inc.
   This file is part of the GNU C Library.


   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.


   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.


   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */


/*
 *	ISO C99 Standard: 7.10/5.2.4.2.1 Sizes of integer types	<limits.h>
 */ 
*/

#ifndef _LIBC_LIMITS_H_
#define _LIBC_LIMITS_H_	1

#include <features.h>


/* Maximum length of any multibyte character in any locale.
   We define this value here since the gcc header does not define
   the correct value.  */
#define MB_LEN_MAX	16


/* If we are not using GNU CC we have to define all the symbols ourself.
   Otherwise use gcc's definitions (see below).  */
#if !defined __GNUC__ || __GNUC__ < 2

/* We only protect from multiple inclusion here, because all the other
   #include's protect themselves, and in GCC 2 we may #include_next through
   multiple copies of this file before we get to GCC's.  */
# ifndef _LIMITS_H
#  define _LIMITS_H	1

#include <bits/wordsize.h>

/* We don't have #include_next.
   Define ANSI <limits.h> for standard 32-bit words.  */

/* These assume 8-bit `char's, 16-bit `short int's,
   and 32-bit `int's and `long int's.  */

/* Number of bits in a `char'.	*/
#  define CHAR_BIT	8

/* Minimum and maximum values a `signed char' can hold.  */
#  define SCHAR_MIN	(-128)
#  define SCHAR_MAX	127

/* Maximum value an `unsigned char' can hold.  (Minimum is 0.)  */
#  define UCHAR_MAX	255

/* Minimum and maximum values a `char' can hold.  */
#  ifdef __CHAR_UNSIGNED__
#   define CHAR_MIN	0
#   define CHAR_MAX	UCHAR_MAX
#  else
#   define CHAR_MIN	SCHAR_MIN
#   define CHAR_MAX	SCHAR_MAX
#  endif

/* Minimum and maximum values a `signed short int' can hold.  */
#  define SHRT_MIN	(-32768)
#  define SHRT_MAX	32767

/* Maximum value an `unsigned short int' can hold.  (Minimum is 0.)  */
#  define USHRT_MAX	65535

/* Minimum and maximum values a `signed int' can hold.  */
#  define INT_MIN	(-INT_MAX - 1)
#  define INT_MAX	2147483647

/* Maximum value an `unsigned int' can hold.  (Minimum is 0.)  */
#  define UINT_MAX	4294967295U

/* Minimum and maximum values a `signed long int' can hold.  */
#  if __WORDSIZE == 64
#   define LONG_MAX	9223372036854775807L
#  else
#   define LONG_MAX	2147483647L
#  endif
#  define LONG_MIN	(-LONG_MAX - 1L)

/* Maximum value an `unsigned long int' can hold.  (Minimum is 0.)  */
#  if __WORDSIZE == 64
#   define ULONG_MAX	18446744073709551615UL
#  else
#   define ULONG_MAX	4294967295UL
#  endif

#  ifdef __USE_ISOC99

/* Minimum and maximum values a `signed long long int' can hold.  */
#   define LLONG_MAX	9223372036854775807LL
#   define LLONG_MIN	(-LLONG_MAX - 1LL)

/* Maximum value an `unsigned long long int' can hold.  (Minimum is 0.)  */
#   define ULLONG_MAX	18446744073709551615ULL

#  endif /* ISO C99 */

# endif	/* limits.h  */
#endif	/* GCC 2.  */

#endif	/* !_LIBC_LIMITS_H_ */

 /* Get the compiler's limits.h, which defines almost all the ISO constants.

    We put this #include_next outside the double inclusion check because
    it should be possible to include this file more than once and still get
    the definitions from gcc's header.  */
#if defined __GNUC__ && !defined _GCC_LIMITS_H_
/* `_GCC_LIMITS_H_' is what GCC's file defines.  */
# include_next <limits.h>
#endif

/* The <limits.h> files in some gcc versions don't define LLONG_MIN,
   LLONG_MAX, and ULLONG_MAX.  Instead only the values gcc defined for
   ages are available.  */
#if defined __USE_ISOC99 && defined __GNUC__
# ifndef LLONG_MIN
#  define LLONG_MIN	(-LLONG_MAX-1)
# endif
# ifndef LLONG_MAX
#  define LLONG_MAX	__LONG_LONG_MAX__
# endif
# ifndef ULLONG_MAX
#  define ULLONG_MAX	(LLONG_MAX * 2ULL + 1)
# endif
#endif

#ifdef	__USE_POSIX
/* POSIX adds things to <limits.h>.  */
# include <bits/posix1_lim.h>
#endif

#ifdef	__USE_POSIX2
# include <bits/posix2_lim.h>
#endif

#ifdef	__USE_XOPEN
# include <bits/xopen_lim.h>
#endif


注意一点:对于不带signed 或unsigned 关键字的char型,C 标准规定这是Implementation Defined ,编译器可以定义char型是无符号的,也可以定义char型是有符号的,在该编译器所对应的体系结构上哪种实现效率高就可以采用哪种实现,x86 平台的gcc 定义char是有符号的。这也是C 标准的Rationale之一:优先考虑效率,而可移植性尚在其次。另外,除了char型以外的整数类型(short,int,long,long long)如果不明确写signed 或unsigned 关键字都表示有符号数,这一点是C 标准明确规定的。

有符号数在计算机中的表示形式是Sign and Magnitude 、1's Complement还是2's Complement?C 标准也没有明确规定,也是Implementation Defined 。大多数体系结构都采用2's Complement表示形式和加减运算规则,x86 平台也是如此。

注意,ASCII码的取值范围是0~127 ,所以不管char型是有符号的还是无符号的,存一个ASCII码都没有问题,一般来说,如果用char型存ASCII码字符,就不必明确写signed 还是unsigned ,如果把char型当作8 位的整数来用,为了可移植性就必须写明是signed 还是unsigned 。

如果不是为了效率,一般来说就没有理由故意写不可移植的代码。比如Linux内核代码使用了很多gcc 特性以得到最佳的执行效率,在写的时候就没打算用别的编译器编译,也就没考虑可移植性的问题。可见C 语言与平台和编译器是密不可分的,离开了具体的平台和编译器讨论C 语言必然难以深入


C 标准规定的浮点型有float、double 、long double ,和整数类型一样,既没有规定每种类型占多少字节,也没有规定采用哪种表示形式。浮点数的实现在各种平台上差异很大,x86 处理器通常是有浮点运算单元的,遵循IEEE 754,float型通常是32位,double 型通常是64位。要详细了解浮点数的IEEE表示可以查看CSAPP的第二章2.4.2 .具体的定义可以查看float.h


(文中部分内容摘自宋劲彬老师的文章)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/simon_uestc/article/details/19687299

智能推荐

Delphi 解析JSON_delphi json解析-程序员宅基地

文章浏览阅读1k次。亲测在 RAD Studio 10.3 正常参考数据{ "五班": [ { "姓名": "张三", "成绩": 75.5 }, { "姓名": "李四", "成绩": 21.7 }, { "姓名": "王五", "成绩": 75.52 }, {_delphi json解析

Java web编写的学生选课系统 完整源码、附详细的设计文档_java web课本学生课程实例源代码-程序员宅基地

文章浏览阅读1.4k次,点赞3次,收藏18次。本系统的分两种用户类型:学生和系统管理员。其中学生用户包括浏览信息自己的信息、修改个人信息的维护,添加选课信息,删除选课信息,查看自己的选课信息(包括选修课程分数,必修课程分数,总课程分数);系统管理员的操作包括用户的增删改、课程的增删改查等。本项目就是对上述业务进行网络信息化管理。整个系统代码完整,下载后可以直接运行,同时附带详细的设计文档!!_java web课本学生课程实例源代码

element ui - el-table 设置表头背景颜色和字体颜色_element 表头设置颜色-程序员宅基地

文章浏览阅读6.9k次,点赞3次,收藏8次。但是对 thead,thead tr,.el-table__cell 元素进行设置,都是无效的,查询了 elementui官网,发现需要使用。在使用 elementui 中的 el-table 时,由于默认表格样式与设计稿不符,需要将表头的背景色和字体颜色设置为新颜色。_element 表头设置颜色

Labview VISA实现串口通信实例讲解 转_labview的visa资源名称显示端口说明-程序员宅基地

文章浏览阅读1.1w次,点赞3次,收藏37次。1.安装VISA驱动VISA驱动不含在软件包中,必须要自己去下载。VISA(Virtual Instrument SoftwareArchitecture,简称为"Visa"),即虚拟仪器软件结构,是VXIplug&amp;play联盟制定的I/O接口软件标准及其规范的总称。VISA提供用于仪器编程的标准I/O函数库,称为VISA库。VISA函数库驻留在计算机系统内,是计算机与仪器的标准..._labview的visa资源名称显示端口说明

005_mini2440裸机读写sdram_裸机内存读写-程序员宅基地

文章浏览阅读237次。1、查看sdram原理图由上图我们看出使用了两片16位数据宽度sdram芯片构成了一个32位数据宽度,读写数据都是以32位来操作。从上图中我们还可以恶获取到sdram的片选信号nSCS连接在nGCS6,即对应着bank 6。2、sdram寄存器配置1)BUS WIDTH & WAIT CONTROL REGISTER (BWSCON)该寄存器用于配置内存的位宽,..._裸机内存读写

JVXETable中禁用某一行的解决方法_jeecg jvxetable 某条数据禁用-程序员宅基地

文章浏览阅读2.6k次。最近在使用jeecg做后台管理系统,遇到了jvxtable中需要禁用某一行的需求按照官网的demo写法,只是实现了所有的cell禁止编辑,禁止选中还是不行!相关的资料太少了,尝试了很多方法都为解决,于是找到了他们的框架底层vxe-table传送门然后再我的组件里面增加了这个配置这样就实现了,禁用当前id这样的选中!!效果如第一张图片所示boot3框架内部demo却没有这么复杂,也实现了这个禁用某行的效果!不知道是哪个步骤的骚操作实现的,有知道的大神可以告知下,多谢了!!..._jeecg jvxetable 某条数据禁用

随便推点

小学四年级计算机教学工作总结,小学科学四年级上册教学工作总结(精选5篇)...-程序员宅基地

文章浏览阅读353次。小学科学四年级上册教学工作总结(精选5篇)光阴如水,忙碌而又充实的工作又将告一段落了,回顾这段时间的教学,收获的不仅岁月,还有成长,立即行动起来写一份教学总结吧。但是教学总结基本的方法论,你掌握了吗?下面是小编为大家收集的小学科学四年级上册教学工作总结(精选5篇),仅供参考,希望能够帮助到大家。小学科学四年级上册教学工作总结1转眼间,一个学期的教学工作结束了,为能更好的提高教育教学质量,先将本学期..._小学计算机与科学教学总结

SpringCloud全家桶(四):搞定微服务网关 Spring Cloud Gateway_spring cloud gateway netty port-程序员宅基地

文章浏览阅读6.7k次,点赞3次,收藏7次。Spring Cloud Gateway 是 springcloud 全新推出的第二代微服务网关,基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术,用来替代Zuul。Gateway不仅提供了统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,如转发、限流、熔断监控和权限校验等。Spring Cloud Gateway 的..._spring cloud gateway netty port

运行链码问题_have (<-chan time.time, string, string)-程序员宅基地

文章浏览阅读239次。go-kit版本问题问题:# github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/core/operations/root/go/pkg/mod/github.com/hyperledger/[email protected]/internal/github.com/hyperledger/fabric/core/operations/system.go:225:23: not enough ar_have (<-chan time.time, string, string)

linux文件头出现非ascii字符_interpreting non ascii codepoint-程序员宅基地

文章浏览阅读3k次。自从用文本编辑器打开了脚本文件后,所有文件执行的时候都会报错Interpreting non ascii codepoint. 用vim打开文件,看不出有什么问题。但是执行head -1 yourscript | od -c之后,看到文本开头有357 273 277三个神奇的字符。解决方法是在vim中输入:set nobomb并保存即可_interpreting non ascii codepoint

thinkphp无法加载数据库驱动: Think\Db\Driver\_/thinkphp/library/think/db/driver/mysql.class.php(-程序员宅基地

文章浏览阅读9.7k次。今天做项目的时候加了配置文件导致这个问题很懵逼,上午跑的好好地,1.首先在你输出的页面var_dump(C()); 打印出页面加载的东西,查看结果中是否缺失DB_TYPE等数据库连接数据最后发现自己在config文件中多加了一个引入配置文件的东西,这行影响的,导致加载不到配置文件 /* 加载扩展配置文件 */ 'LOAD_EXT_CONFIG' => '_/thinkphp/library/think/db/driver/mysql.class.php(27)

linux驱动学习记录(二)-PCI驱动框架_struct pci_error_handlers-程序员宅基地

文章浏览阅读9.6k次,点赞3次,收藏13次。1. PCI设备驱动的组成 PCI 驱动只是为了辅助设备本身的驱动,它不是目的,而是手段。例如,对于通过PCI 总线与系统连接的字符设备,则驱动中除了要实现PCI 驱动部分外,其主体仍然是设备作为字符设备本身的驱动,即实现file_operations成员函数并注册cdev。 在Linux 内核中,用pci_driver 结构体来定义PCI 驱动,该结构体中包含了PCI 设备的探测_struct pci_error_handlers