做网站的文案是指,一个网站怎么留住用户,wordpress创建目录,网上怎么开店卖产品目录 1.C语言中static、const、volatile关键字用法区别#xff1b;
static的用法#xff08;定义和用途)
const的用法#xff08;定义和用途#xff09;
volatile (英文意思为易变的) 作用和用法#xff1a; 2.C语言中#xff0c;const 和 static 的区别#xff0c;c…目录 1.C语言中static、const、volatile关键字用法区别
static的用法定义和用途)
const的用法定义和用途
volatile (英文意思为易变的) 作用和用法 2.C语言中const 和 static 的区别char * const 和 const * char的区别
3.变量声明和定义的区别:
4.C语言编译后的内存分布
5.C语言内存分区未定义的全局变存放在哪个区
6.静态局部变量存储在静态区那么静态区的创建和消失是在什么时候?
7.变量加入static以后在内存中存储位置的变化
8.在windows里面运行了多个进程其中一个进程执行完了它的静态区会如何处理
9.连续调用同一个函数两次它的局部变量初始化结果是否会一致
10.静态局部变量与局部变量的区别为什么局部变量未定义时每次初始化的结果是不确定的是个真随机数还是个伪随机数
11.快排时间复杂度怎么计算的
12.用熟悉的编译器手写栈和冒泡排序 1.C语言中static、const、volatile关键字用法区别
static的用法定义和用途) 1用static修饰局部变量使其变为静态存储方式(静态数据区)那么这个局部变量在函数执行完成之后不会被释放而是继续保留在内存中。 2用static修饰全局变量使其只在本文件内部有效而其他文件不可连接或引用该变量。 3用static修饰函数对函数的连接方式产生影响使得函数只在本文件内部有效对其他文件是不可见的这一点在大工程中很重要很重要避免很多麻烦很常见。这样的函数又叫作静态函数。使用 静态函数的好处是不用担心与其他文件的同名函数产生干扰另外也是对函数本身的一种保护机制。
const的用法定义和用途 const主要用来修饰变量、函数形参和类成员函数 1用const修饰常量定义时就初始化以后不能更改。 2用const修饰形参func(const int a){};该形参在函数里不能改变 3用const修饰类成员函数该函数对成员变量只能进行只读操作就是const类成员函数是不能修改成员变量的数值的。被const修饰的东西都受到强制保护可以预防意外的变动能提高程序的健壮性。
1.const int a; 2.int const a; 3.const int *a; 4.int * const a; 5.int const * a const;
前两个的作用是一样a是一个常整型数。
常指针从右往左读以*为分界
第三个意味着a是一个指向常整型数的指针也就是整型数是不可修改的但指针可以。 第四个意思a是一个指向整型数的常指针也就是说指针指向的整型数是可以修改的但指针是不可修改的。 最后一个意味着a是一个指向常整型数的常指针也就是说指针指向的整型数是不可修改的同时指针也是不可修改的。
volatile (英文意思为易变的) 作用和用法 一个定义为volatile的变量是说这变量可能会被意想不到地改变这样编译器就不会去假设这个变量的值了。精确地说就是优化器在用到这个变量时必须每次都小心地重新读取这个变量在内存中的值而不是使用保存在寄存器里的备份虽然读写寄存器比读写内存快。 以下几种情况都会用到volatile
并行设备的硬件寄存器如状态寄存器 一个中断服务子程序中会访问到的非自动变量 多线程应用中被几个任务共享的变量 2.C语言中const 和 static 的区别char * const 和 const * char的区别
const 关键字用于定义常量即在程序运行期间不可修改的值。const 可以用于修饰变量、函数参数和函数返回值。使用 const 可以提高程序的可读性和安全性。
static 关键字用于定义静态变量或函数。静态变量在程序运行期间只会被初始化一次而静态函数只能在当前文件中被调用。使用 static 可以控制变量和函数的作用域避免命名冲突和不必要的访问。
char * const 和 const * char 的区别在于指针指向的内容是否可以被修改。char * const 表示指针本身是常量即指针指向的地址不可修改但指针指向的内容可以修改而 const * char 表示指针指向的内容是常量即指针指向的内容不可修改但指针本身可以修改。
3.C语言字节对齐、结构体对齐
什么是字节对齐
在C语言中结构是一种复合数据类型其构成元素既可以是基本数据类型如int、long、float等的变量也可以是一些复合数据类型如数组、结构、联合等的数据单元。在结构中编译器为结构的每个成员按其自然边界alignment分配空间。各个成员按照它们被声明的顺序在内存中顺序存储第一个成员的地址和整个结构的地址相同。
为了使CPU能够对变量进行快速的访问,变量的起始地址应该具有某些特性,即所谓的”对齐”. 比如4字节的int型,其起始地址应该位于4字节的边界上,即起始地址能够被4整除.
字节对齐有什么作用
需要字节对齐的根本原因在于CPU访问数据的效率问题。假设变量的地址不是自然对齐取它的值的话需要访问多次内存而如果变量在自然对齐位置上则只要一次就可以取出数据。
正确处理字节对齐 对于标准数据类型它的地址只要是它的长度的整数倍就行了而非标准数据类型按下面的原则对齐 数组 按照基本数据类型对齐第一个对齐了后面的自然也就对齐了。 联合 按其包含的长度最大的数据类型对齐。 结构体 结构体中每个数据类型都要对齐。
结构体各成员的起始位置相对于结构体变量的起始位置的偏移量应该为该结构体成员类型所占字节数与pack(n)的n取最小值的倍数 • 结构体变量所占字节数应该是结构体各成员所占字节数的最大值与pack(n)的n取最小值
举例说明
例1
struct test { char x1; short x2; float x3; char x4; };
由于编译器默认情况下会对这个struct作自然边界有人说“自然对界”我觉得边界更顺口对齐结构的第一个成员x1其偏移地址为0占据了第1个字节。第二个成员x2为short类型其起始地址必须2字节对界因此编译器在x2和x1之间填充了一个空字节。结构的第三个成员x3和第四个成员x4恰好落在其自然边界地址上在它们前面不需要额外的填充字节。在test结构中成员x3要求4字节对界是该结构所有成员中要求的最大边界单元因而test结构的自然对界条件为4字节编译器在成员x4后面填充了3个空字节。整个结构所占据空间为12字节。
例2
#pragma pack(1) //让编译器对这个结构作1字节对齐 struct test { char x1; short x2; float x3; char x4; }; #pragma pack() //取消1字节对齐恢复为默认4字节对齐
这时候sizeof(struct test)的值为8。
变量声明和定义的区别:
变量声明只是变量的说明在程序中不需要为其分配内存空间而变量定义是为变量分配内存空间并初始化
4.C语言编译后的内存分布
C语言编译后的内存分布通常包括以下几个部分
1. 代码段Text Segment也称为只读代码段存放程序的机器指令。在程序运行时代码段是只读的不允许修改。
2. 数据段Data Segment存放已初始化的全局变量和静态变量。在程序加载时数据段的大小是固定的。
3. BSS段Block Started by Symbol存放未初始化的全局变量和静态变量。在程序加载时BSS段的大小是固定的但是实际上并不占用磁盘空间只是在程序运行时根据需要分配内存。
4. 堆Heap用于动态分配内存。在程序运行时可以通过函数如malloc()和free()来动态地分配和释放堆内存。
5. 栈Stack用于存放函数的局部变量、函数参数和函数调用的上下文信息。栈是一种后进先出LIFO的数据结构每次函数调用时会在栈上分配一块内存函数返回时会释放这块内存。
6. 环境变量区域存放环境变量的值。
7. 命令行参数区域存放命令行参数的值
5.C语言内存分区未定义的全局变存放在哪个区
bss段:未初始化或初始化未0的全局变量和静态变量,具体体现为 一个占位符,不占用.exe文件空间,其内容由操作系统初始化/清零
6.静态局部变量存储在静态区那么静态区的创建和消失是在什么时候?
静态区是在程序运行时由操作系统分配的一块内存空间它的创建和消失与程序的生命周期有关。静态局部变量在程序运行时只会被初始化一次它们的内存空间会一直存在直到程序结束。因此静态区的创建和消失是在程序启动时创建在程序结束时销毁。
7.变量加入static以后在内存中存储位置的变化
当一个变量被声明为static时它的存储位置会从栈stack或堆heap转移到静态存储区static storage area也称为全局数据区global data area。
在栈或堆中声明的变量是在函数调用时动态分配的当函数返回时它们的存储空间会被释放。而在静态存储区中声明的变量则在程序运行期间一直存在直到程序结束才会被释放。
因此使用static声明的变量可以在多个函数之间共享而不需要通过参数传递或全局变量来实现。此外静态变量的初始值只会被赋值一次即使函数被多次调用它的值也会保持不变。
8.在windows里面运行了多个进程其中一个进程执行完了它的静态区会如何处理 当一个进程执行完毕后操作系统会回收该进程的资源包括其地址空间。在回收过程中操作系统会释放该进程所占用的内存空间包括静态区。释放静态区的具体处理方式取决于操作系统的实现。
一般情况下操作系统会将静态区的内存空间标记为可用以便其他进程可以重新使用。但是静态区中的数据并不会立即被清除而是等待下一个进程使用该内存空间时进行覆盖。因此在下一个进程使用该静态区之前原来进程的数据可能仍然存在于内存中。
9.连续调用同一个函数两次它的局部变量初始化结果是否会一致
一般情况下连续调用同一个函数两次它的局部变量初始化结果不会一致。这是因为每次函数调用时局部变量都会重新初始化。如果函数中的局部变量没有被显式地初始化那么它们的值将是未定义的可能会导致不同的结果。但是如果函数中的局部变量被显式地初始化为相同的值那么它们的值将是一致的。
10.静态局部变量与局部变量的区别为什么局部变量未定义时每次初始化的结果是不确定的是个真随机数还是个伪随机数
静态局部变量和局部变量的区别在于它们的生命周期和作用域不同。静态局部变量在函数内部定义但是它们的生命周期是整个程序运行期间而不是函数调用期间。而局部变量的生命周期只在函数调用期间存在。
当局部变量未定义时每次初始化的结果是不确定的。这是因为未初始化的局部变量的值是未定义的它们的值取决于它们在内存中的位置和之前存储在该位置的值。因此每次初始化的结果可能是不同的。
这些值通常是伪随机数而不是真随机数。伪随机数是通过算法生成的数字序列看起来像是随机的但实际上是可预测的。在C语言中未初始化的局部变量通常会被分配为内存中的随机值这些值通常是伪随机数。
11.快排时间复杂度怎么计算的
快速排序的时间复杂度可以通过递归树来计算。在最坏情况下每次划分都只能将序列分成一个元素和n-1个元素这样递归树的深度就是n每层的时间复杂度都是O(n)因此最坏情况下的时间复杂度是O(n^2)。
在平均情况下每次划分都能将序列分成大小大致相等的两个子序列递归树的深度是logn每层的时间复杂度都是O(n)因此平均情况下的时间复杂度是O(nlogn)。
最好情况下每次划分都能将序列分成大小相等的两个子序列递归树的深度是logn每层的时间复杂度都是O(n)因此最好情况下的时间复杂度也是O(nlogn)。
因此快速排序的时间复杂度在最坏情况下是O(n^2)在平均情况下和最好情况下都是O(nlogn)。
12.用熟悉的编译器手写栈和冒泡排序
#define MAX_SIZE 100typedef struct {int data[MAX_SIZE];int top;
} Stack;// 初始化栈
void initStack(Stack *stack) {stack-top -1;
}// 判断栈是否为空
int isEmpty(Stack *stack) {return stack-top -1;
}// 判断栈是否已满
int isFull(Stack *stack) {return stack-top MAX_SIZE - 1;
}// 入栈
void push(Stack *stack, int value) {if (isFull(stack)) {printf(Stack is full. Cannot push element.
);return;}stack-data[stack-top] value;
}// 出栈
int pop(Stack *stack) {if (isEmpty(stack)) {printf(Stack is empty. Cannot pop element.
);return -1;}return stack-data[stack-top--];
}// 获取栈顶元素
int peek(Stack *stack) {if (isEmpty(stack)) {printf(Stack is empty. Cannot peek element.
);return -1;}return stack-data[stack-top];
}int main() {Stack stack;initStack(stack);push(stack, 1);push(stack, 2);push(stack, 3);printf(Top element: %d
, peek(stack));printf(Popped element: %d
, pop(stack));printf(Popped element: %d
, pop(stack));printf(Top element: %d
, peek(stack));return 0;
}
void bubble_sort(int arr[], int n) {int i, j, temp;for (i 0; i n - 1; i) {for (j 0; j n - i - 1; j) {if (arr[j] arr[j 1]) {temp arr[j];arr[j] arr[j 1];arr[j 1] temp;}}}
}int main() {int arr[] {5, 2, 8, 3, 1, 6};int n sizeof(arr) / sizeof(arr[0]);int i;printf(Before sorting: );for (i 0; i n; i) {printf(%d , arr[i]);}printf(
);bubble_sort(arr, n);printf(After sorting: );for (i 0; i n; i) {printf(%d , arr[i]);}printf(
);return 0;
}