做网站 网上接单,昆明本地网站,wordpress放视频,wordpress修改个人头像C语言标准定义了32个关键字 union声明联合数据类型
Union declaration - cppreference.com维护足够的空间来置放多个数据成员中的“一种”#xff0c;而不是为每一个数据成员配置空间#xff0c;在 union 中所有的数据成员共用一个空间#xff0c;同一时间只能储存其中一个…C语言标准定义了32个关键字 union声明联合数据类型
Union declaration - cppreference.com维护足够的空间来置放多个数据成员中的“一种”而不是为每一个数据成员配置空间在 union 中所有的数据成员共用一个空间同一时间只能储存其中一个数据成员所有的数据成员具有相同的起始地址
union StateMachine
{char character;int number; char *str; double exp;
};
一个 union 只配置一个足够大的空间以来容纳最大长度的数据成员以上例而言最大 长度是 double 型态所以 StateMachine 的空间大小就是 double 数据类型的大小。union主要目的是为了压缩数据存储的空间如果变量不会在同一时间被使用到就可以使用 union enum声明枚举类型
Enumeration declaration - cppreference.com
rigister 声明寄存器变量
Storage class specifiers - cppreference.comhttps://en.wikibooks.org/wiki/C%2B%2B_Programming/Programming_Languages/C%2B%2B/Code/Keywords/register这个关键字请求编译器尽可能的将变量存在 CPU 内部寄存器中而不是通过内存寻址访问以提高效率。注意是尽可能不是绝对。因为 CPU 的寄存器有限注意: 寄存器在 c 和 c之间有不同的语义。在 c 语言中可以通过声明数组寄存器来禁止数组到指针的转换: register int a [1] ; 从 C 17 开始auto 关键字不再是 C 存储类说明符且 register 关键字被弃用这意味着变量的最大尺寸等于寄存器的大小通常是一个词且不能对它应用一元的 运算符因为它没有内存位置。存储空间分配不同auto类型分配在栈上属于动态存储类别占动态存储区空间函数调用结束后自动释放而static分配在静态存储区在程序整个运行期间都不释放。两者之间的作用域相同但生存期不同static局部变量在所处模块的初次运行时进行初始化工作且只初始化一次。对于局部静态变量如果不赋初值编译期会自动赋初值0或空字符而auto类型的初值是不确定的。(对于C中的class对象例外class的对象实例如果不初始化则会自动调用默认构造函数不管是否是static类型) register 变量必须是 能被 CPU 寄存器所接受的类型。意味着 register 变量必须是一个单个的值并且其长度应小 于或等于整型的长度
volatile说明变量类型可以被隐含改变
cv (const and volatile) type qualifiers - cppreference.com编 译器对访问该变量的代码就不再进行优化从而可以提供对特殊地址的稳定访问const volatile修饰的变量 - Jeremys blog
int i10;
int j i;//(1)语句
int k i;//(2)语句
这时候编译器对代码进行优化因为在(1)、(2)两条语句中i 没有被用作左值。这时候 编译器认为 i 的值没有发生改变所以在(1)语句时从内存中取出 i 的值赋给 j 之后这个 值并没有被丢掉而是在(2)语句时继续用这个值给 k 赋值。编译器不会生成出汇编代码 重新从内存里取 i 的值这样提高了效率。但要注意:(1)、(2)语句之间 i 没有被用作左 值才行。
volatile int i10;
int j i;//(3)语句
int k i;//(4)语句 volatile 关键字告诉编译器 i 是随时可能发生变化的每次使用它的时候必须从内存中取出 i 的值因而编译器生成的汇编代码会重新从 i 的地址处读取数据放在 k 中。这样看来如果 i 是一个寄存器变量或者表示一个端口数据或者是多个线程的共享数 据就容易出错所以说 volatile 可以保证对特殊地址的稳定访问。 但是注意:在 VC6.0 中一般 Debug 模式没有进行代码优化所以这个关键字的作 用有可能看不出来。你可以同时生成 Debug 版和 Release 版的程序做个测试。
mutable 存储类
mutable 说明符仅适用于类的对象这将在本教程的最后进行讲解。它允许对象的成员替代常量。也就是说mutable 成员可以通过 const 成员函数修改。
thread_local 存储类
使用 thread_local 说明符声明的变量仅可在它在其上创建的线程上访问。 变量在创建线程时创建并在销毁线程时销毁。 每个线程都有其自己的变量副本。thread_local 说明符可以与 static 或 extern 合并。可以将 thread_local 仅应用于数据声明和定义thread_local 不能用于函数声明或定义。以下演示了可以被声明为 thread_local 的变量
thread_local int x; // 命名空间下的全局变量
class X
{static thread_local std::string s; // 类的static成员变量
};
static thread_local std::string X::s; // X::s 是需要定义的void foo()
{thread_local std::vectorint v; // 本地变量
}
定义
所谓的定义就是(编译器)创建一个对象为这个对象分配一块内存取上一个名字这个名字就是变量名或对象名。但注意这个名字一旦和 这块内存匹配起来它们就同 生共死终生不离不弃。并且这块内存的位置也不能被改变。一个变量或对象在一定的区 域内(比如函数内全局等)只能被定义一次如果定义多次编译器会提示你重复定义 同一个变量或对象。
声明 两重含义
第一重
通知编译器变量名字 已经匹配到一块内存空间此刻出现的变量或对象是在别的地方已经定义过了声明可以出现多次
第二重
通知编译器名字已经提前预定了别的地方再也不能用它来作为变量名或对象名例子void fun(int i, char c);
例子
int i; 定义 extern int i; 声明
重点
定义声明最重要的区别:定义创建了对象并为这个对象分配了内存声明没有分配内存
基本数据类型 使用sizeof 查看具体平台数据类型的大小
命名规则 所有宏定义、枚举常数、只读变量全用大写字母命名用下划线分割单词。
const int MAX_LENGTH 100; //这不是常量而是一个只读变量具体请往后看
#define FILE_PATH “/usr/tmp”
定义变量的同时千万千万别忘了初始化。因为定义变量时编译器并不一定清空了 这块内存它的值可能是无效的数据不同类型数据之间的运算要注意精度扩展问题一般低精度数据将向高精度 数据扩展。
sizeof
sizeof(p) 和 sizeof(*p)的区别sizeof(p)是指针类型64位平台是832位平台是4sizeof(*p) 是指针指向的数据类型的大小如果是long double就是16double是8int 是4
int main(){long double *p nullptr;std::cout sizeof(p) std::endl;std::cout sizeof(*p) std::endl;
}
int main(){int a[100];std::cout sizeof(a) std::endl; //400std::cout sizeof(a) std::endl; //8std::cout sizeof(a[0]) std::endl;//8
}
#include iostreamint b[100];
void fun(int b[100]){std::cout sizeof(b) std::endl; //8
}int main(){fun(b);
}
#include iostream
#include cstringint main(){char a[1000];for (int i 0; i 1000; i) {a[i] -1 - i;}printf(%d,strlen(a));
}
for 循环内当 i 的值为 0 时a[0]的值为-1。关键就是-1 在内存里面如何存储。计算机系统中数值一律用补码来表示(存储)。主要原因是使用补码可以将符号位和其它位统一处理;同时减法也可按加法来处理。另外两个用补码表示的数 相加时如果最高位(符号位)有进位则进位被舍弃。正数的补码与其原码一致;负数的 补码:符号位为 1其余位为该数绝对值的原码按位取反然后整个数加 1。 按照负数补码的规则可以知道-1 的补码为 0xff-2 的补码为 0xfe......当 i 的值为 127 时a[127]的值为-128而-128 是 char 类型数据能表示的最小的负数。当 i 继续增加a[128] 的值肯定不能是-129。因为这时候发生了溢出-129 需要 9 位才能存储下来而 char 类型 数据只有 8 位所以最高位被丢弃。剩下的 8 位是原来 9 位补码的低 8 位的值即 0x7f。 当 i 继续增加到 255 的时候-256 的补码的低 8 位为 0。然后当 i 增加到 256 时-257 的补 码的低 8 位全为 1即低八位的补码为 0xff如此又开始一轮新的循环......按照上面的分析a[0]到 a[254]里面的值都不为 0而 a[255]的值为 0。strlen 函数是计 算字符串长度的并不包含字符串最后的‘\0’。而判断一个字符串是否结束的标志就是看 是否遇到‘\0’。如果遇到‘\0’则认为本字符串结束。分析到这里strlen(a)的值为 255 应该完全能理解了。这个问题的关键就是要明白 char 类型默认情况下是有符号的其表示的值的范围为[-128,127]超出这个范围的值会产生溢 出。另外还要清楚的就是负数的补码怎么表示。弄明白了这两点这个问题其实就很简单了。
所谓原码就是前面所介绍的二进制定点表示法即最高位为符号位“0”表示正“1”表示负其余位表示数值的大小。反码表示法规定正数的反码与其原码相同负数的反码是对其原码逐位取反但符号位除外。补码表示法规定正数的补码与其原码相同负数的补码是在其反码的末位加1。根据原码的定义正零和负零的原码为0 : 0000 0000 0000 0000 0000 0000 0000 0000 32 bit)-0 : 1000 0000 0000 0000 0000 0000 0000 0000而反码为0 : 0000 0000 0000 0000 0000 0000 0000 0000-0 : 1111 1111 1111 1111 1111 1111 1111 1111补码为0 : 0000 0000 0000 0000 0000 0000 0000 0000-0 : 1 0000 0000 0000 0000 0000 0000 0000 0000可以看出-0的补码发生溢出舍弃最高位后其跟0在内存的表示一样都是0000 0000 0000 0000 0000 0000 0000 0000
switch case
case 后面只能是整型或字符型的常量或常量表达式(想想字符型数据在内存里 是怎么存的) switch case排列顺序 把正常情况放在前面而把异常情况放在后面按执行频率排列 case 语句switch 里面不可以使用 continue 在switch case 语句中能否使用continue关键字_Keep Fighting All The Time-CSDN博客_switch语句中的continue
循环代码
多重循环中如果有可能应当将最长的循环放在最内层最短的循环放在最外层以减少 CPU 跨切循环层的次数。void
void *可以指向任何类型的数据 void 不能代表一个真实的变量因为没有内存空间
return关键字
c - Return char* from function - Stack Overflow
return char*
函数内新建一个static char数组这样函数结束数组也不会被销毁 / 使用const char * 字符串存储在常量区函数内部动态申请内存使用完需要释放内存全局声明数组不好别人会改函数返回char* 的解决方案_芒果儿-CSDN博客_c 返回char*
const
case 语句后必须是一个常量const 修饰的只读变量仍然是变量所以是不可以的【C语言】const关键字用法 - 代码先锋网const 定义的只读变量从汇编的角度来看只是给出了对应的内存地址而不是象#define 一样给出的是立即数所以const 定义的只读变量在程序运行过程中只有一份拷贝(因为 它是全局的只读变量存放在静态区)而#define 定义的宏常量在内存中有若干个拷贝。 #define 宏是在预编译阶段进行替换而 const 修饰的只读变量是在编译的时候确定其值。#define 宏没有类型而 const 修饰的只读变量具有特定的类型。 const 离哪个近修饰哪个变量不可以改变 修饰函数的参数 告诉编译器 形参输入在函数体中的不能改变从而防止了使用者的一些无意的或错误的修改。 修饰函数的返回值 const 修饰符也可以修饰函数的返回值返回值不可被改变。例如: const int Fun (void);
参考链接
What does sizeof (int) * p semantically mean?c - Difference between sizeof(*p) and sizeof(p)? - Stack Overflowc语言中的 %u 什么意思啊_百度知道
struct关键字
多种数据组合起来的一个整体其表现形式是一个结构体传入传出都是结构体的形式可以压缩传输的参数结构体所占的内存大小是其成员所占内存之和 sizeof(struct)这里还涉及到结构体的内存对齐即使是空的结构体使用sizeof求内存其大小是1主要是为其分配一个地址空类也是一样的
柔性数组
结构中的最后一个元素允许是未知大小的数组这就叫做柔性数组成员但结构中的柔性数组成员前面必须至少一个其他成员。柔性数组成员允许结构中包含一个大小可变的数组。sizeof 返回的这种结构大小不包括柔性数组的内存。包含柔性数组成员的结构用 malloc ()函数进行内存的动态分配并且分配的内存应该大于结构的大小以适应柔性数组的预期大小。用 sizeof(type_a)得到的只有 4就是 sizeof(i)sizeof(int)。那个 0 个元素的数组没有占用空间而后我们可以进行变长操作了。使用malloc分配内存之后使用sizeof探测整体的数据大小仍然是 4柔性数组只是编外人员不占结构体的编制。只是说 在使用柔性数组时需要把它当作结构体的一个成员仅此而已。再说白点柔性数组其实与 结构体没什么关系只是“挂羊头卖狗肉”而已算不得结构体的正式成员当然上面既然用 malloc 函数分配了内存肯定就需要用 free 函数来释放内存这个柔性数组的概念 实际使用很少
#include iostream
#include cstringtypedef struct st_type{int i;int a[];
}type_a;
int main(){std::cout sizeof(type_a) std::endl; //4type_a * p (type_a*) malloc(sizeof (type_a) 100 * sizeof(int));std::cout sizeof(type_a) std::endl; //4free(p);
} 大端模式 和 小端模式
大端模式(Big_endian):字数据的高字节存储在低地址中而字数据的低字节则存放在高地址中。小端模式(Little_endian):字数据的高字节存储在高地址中而字数据的低字节则存放在低地址中。变量i占4个字节但只有一个字节的值为1另外三个字节的值都为0。如果取出低地址上的值为0毫无疑问这是大端模式;如果取出低地址上的值为1毫无疑问这是小端模式。
使用程序验证
#include iostream
#include cstringint checkSystem(){union check{int i;char ch;}c;c.i 1;return (c.ch 1);
}
int main(){int a checkSystem();std::cout a std::endl;
}
直接查看内存 枚举变量的大小实质是常数所占内存空间的大小常数为int类型当前主流的编译器中一般是32位机器和64位机器中int型都是4个字节枚举类型所占内存大小也是这样。参考链接enum枚举变量所占内存大小_bulebin的博客-CSDN博客_枚举类型大小