关于C语言以及linux系统的知识点
scanf()根据一个%d读取一个数值
每次读取前都跳过数值前的所有空白字符(空格、tab、换行符)
直到遇到非空白字符才开始读取
scanf的返回值,成功返回输入项目的个数
ret = scanf(“%d”, &chose);
if (ret != 1) {
printf(“input chose error\n”);
return -1;
}
字符型数组在内存中的储存方式同String类一样,
故输出数组名并不是输出数组首地址,而是直接输出数组内容直到/0;
而整形数组只是整形的集合,所以其数组名仅仅是其首地址,
我们必须要用for循环才能完整的输出整个整形数组
判断大小端存储
小端存储(X86):数据低位存储在地址低位,数据高位存储在地址高位
大端存储:数据低位存储在地址高位,数据高位存储在地址低位
#include <stdio.h>
int main(int argc, const char *argv[])
{//方法1:指针
// int a = 0x12345678;
// char *p = (char *)&a;
// if (0x78 == *p)
// {
// printf(“小端\n”);
// }
// else if (0x12 == *p)
// {
// printf(“大端\n”);
// }
//方法2:联合体
union A
{
int a;
char b;
};
union A n;
n.a = 0x12345678;
if (0x78 == n.b)
{
printf("小端\n");
}
else if (0x12 == n.b)
{
printf("大端\n");
}
return 0;
}
unsigned 在32位和64位系统中都占用4字节
struct C {
char s[0];
};
//此时数组是s为柔性数组,在构造体中不分配空间,所以字节数为0
printf(“%d\n”,sizeof(struct C));//0字节
柔性数组参考csdn链接
https://blog.csdn.net/weixin_42096901/article/details/117331944?ops_request_misc=&request_id=&biz_id=102&utm_term=%E6%9F%94%E6%80%A7%E6%95%B0%E7%BB%84&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-0-117331944.nonecase&spm=1018.2226.3001.4187
C高级day3 3动态申请分配内存
栈区分配空间是根据定义实时向下申请,生命周期结束后自动被系统回收
堆区是由malloc动态申请 从下向上方式申请 整个程序结束或者free释放
当栈区和堆区申请内存碰头时间,表示系统内存空间满
换行的方式
puts(""); putchar(10); putchar('\n'); putchar('\12');
putchar('\xa'); printf("\n");
当用scanf输入时,可能会产生垃圾字符,
可以用 while(getchar()!=(‘\n’)) 处理
用malloc申请空间时间,可以根据返回值判断申请内存是否成功
int n=malloc(sizeof(int [10]))
if(NULL==n){
printf(“内存申请失败,请重试”);
}
if (a != NULL) {
free(a); //释放a指向的内存,但是释放后a指向的这个指针并没有断开
a = NULL; //断开指针指向
}
冒泡排序函数的封装
#include <stdio.h>
//冒泡排序的升降函数
//flag 0 升序 1 降序
int sort(int *p, int len, int flag){
if(NULL == p){
printf("入参为NULL,排序失败\n");
return -1;
}
int i = 0;
int j = 0;
int temp = 0;
if(0 == flag){
for(i = 0; i < len-1; i++){
for(j = 0; j < len-1-i; j++){
if(p[j] > p[j+1]){
temp = p[j];
p[j] = p[j+1];
p[j+1] = temp;
}
}
}
}else if(1 == flag){
for(i = 0; i < len-1; i++){
for(j = 0; j < len-1-i; j++){
if(*(p+j) < *(p+j+1)){
temp = *(p+j);
*(p+j) = *(p+j+1);
*(p+j+1) = temp;
}
}
}
}
return 0;
}
int print_array(int *p, int len){
int i = 0;
for(i = 0; i < len; i++){
printf("%d ", p[i]);
}
putchar(10);
}
int main(int argc, const char *argv[])
{
int s[5] = {67, 45, 18, 96, 10};
print_array(s, 5);
sort(s, 5, 0);
print_array(s, 5);
sort(s, 5, 1);
print_array(s, 5);
return 0;
}
优化后的冒泡排序
stu_t stu;
int i,j,flag;
for(i=0;i<cls->n;i++){
for(j=0;j<cls->n;j++){
if(cls->stu[j].score > cls->stu[j+1].score ){
stu = cls->stu[j];
cls->stu[j] = cls->stu[j+1];
cls->stu[j+1] = stu;
flag=1;
}
}
if(0==flag){//表示上一步没有进入if循环,此时已经有序排列,减少了多余的排列
break;
}
}
删除思想
//2.删除功能的实现
//功能:根据输入的学生姓名,删除对应的学生
//参数:班级的指针
//返回值:成功返回删除的学生个数,失败则返回-1
int del_student (class_t *cls){
char name[20]={0};
//1.判断班级是否为空
if(class_t_empty(cls)){
printf(“班级内没有学生\n”);
return -1;
}
//2.输入删除想要删除的学生名单
printf(“请输入想要删除的学生\n”);
scanf(“%s”,name);
while(getchar()!=‘\n’);
//3.拿输入的学生姓名和班级内的学生进行比较
int i=0,j=0;
for(i=0,j=0;in;i++){
if(strcmp(name,(cls->stu[i].name))){//输入学生的姓名和班级内某个学生相等的时间不进入if语句,i一直加
cls->stu[j]= cls->stu[i]; //不相等就进入if语句,将i此时的下标给到j,完成位置的替换
j++;
}
}
//4.修改班级内n的值
cls->n -= (i-j);
//5.返回值
return (i-j);
}
//字符串的颠倒
#include <stdio.h>
int main(int argc, const char *argv[])
{
char data[12] = "hello world";
char *p1 = data;
char *p2 = data;
while (*p2 != '\0')
{
p2++;
}
p2 -= 1;
char tmp;
while (p2 > p1)
{
tmp = *p1;
*(p1++) = *p2;
*(p2--) = tmp;
}
printf("data = %s\n", data);
return 0;
}
内存清零的函数
从&A地址开始,向后sizeof(struct AA)大小的内存,全部设置为0
memset(&A,0,sizeof(struct AA));
永远不要返回局部变量的地址,作用周期结束后就被系统回收了
栈区:局部变量或者函数的执行 满减栈
32位系统下,寄存器为4字节,cpu从cache(高速缓存区)拿数据要从寄存器中拿数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iyRvxzmg-1658410452600)(C:\Users\admin\Desktop\内存空间.png)]
long double 32位 12字节 64位16字节
sizeof不是函数,可以不加括号使用,是个关键字
typedf 是关键字 在预处理阶段
define是预处理指令
编译分为预处理,编译,汇编,链接
预处理:宏定义的替换和头文件的展开
gcc -E hello.c -o hello.i
编译:做语法分析和词法分析,起到查错的作用,如果语法词法都没有错,生成汇编文件
gcc -S hello.i -o hello.s
汇编:将汇编文件生成二进制文件,用来给计算机识别
gcc -c hello.s -o hello.o
链接:链接库文件(函数的定义),最终生成可执行的a.out文件
//内存清零的函数
//从&A地址开始,向后sizeof(struct AA)大小的内存,全部设置为0
memset(&A,0,sizeof(struct AA));
练习题:
1.下面程序输出的结果为(B)
int main(){
int a[]={1,2,3,4,5,6,7,8,9,10,11,12},*p=a+5,*q=NULL;
*q=*(p+5);//*q指向的是NULL,也就是q没有指向任何变量
//把一个常量赋值给一个不存在的NULL,是行不通的
//可以指向一个新地址
printf("%d %d\n",*p,*q);
}
(B)
A.5 10
B.运行后报错
C.6 11
D.6 6
2.已有定义:
int i,a[10],*p;
则合法的赋值语句是(C)
A.p=a[2]+2;
B.p=a[5];
C.p=a+3;//a此时代表数组的首地址,a+3表示偏移3个int型的数据,此时指针指向a[3]
D.p=100;
3.下面程序输出的结果为(B)
int main(){
int a[]={2,4,6,8,10}, y=0, x, *p;
p=&a[1];
for(x=1; x<3; x++)
y+=p[x];
printf("%d\n", y);
}
A.10
B.14
C.24
D.18
4.设有定义语句
int x[6]={2,4,6,8,5,7},*p=x,i;
要求依次输出x数组6个元素中的值,不能完成此操作的语句是(D)
A.for(i=0;i<6;i++) printf("%2d",*p++);
B.for(i=0;i<6;i++) printf("%2d",*(p++));
C.for(i=0;i<6;i++) printf("%2d",*(p+i));
D.for(i=0;i<6;i++) printf("%2d",(*p)++);
5.下面代码会输出什么? 0
int main(){
char s[] = "ABCD";
char *p;
p = s;
printf("%d\n", *(p+4));
}
6.下面程序输出的结果为(B)
int main(){
char s[] = "hello world";
printf("%d\n",s[strlen(s)-1]-s[sizeof(s)-11]);
}
A.-8
B.-1
C.8
D.1
7.下列的定义及操作,错误的是(D)
A.char s[10] = {'\0'};s[1] = 'H';
B.char s[10] = {'0'};s[1] = 'Q';
C.char s[10] = {0};s[1] = 'Y';
D.char s[] = {'\0'};s[1] = 'J';
s;
printf(“%d\n”, *(p+4));
}
6.下面程序输出的结果为(B)
int main(){
char s[] = “hello world”;
printf(“%d\n”,s[strlen(s)-1]-s[sizeof(s)-11]);
}
A.-8
B.-1
C.8
D.1
7.下列的定义及操作,错误的是(D)
A.char s[10] = {‘\0’};s[1] = ‘H’;
B.char s[10] = {‘0’};s[1] = ‘Q’;
C.char s[10] = {0};s[1] = ‘Y’;
D.char s[] = {‘\0’};s[1] = ‘J’;