#C语言基础 笔记二

强制转换

int a = 5;

float b = a / 2; // 2.000000

float b = (float)a / 2; // 2.500000

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int a = 5;
    float b = (float)a / 2;
    printf("%d %f\n", a, b);
    return 0;
}

分支语句

if

基本结构:

if(表达式)
{
    // 你符合这个条件的时候,就执行语句块1
    语句块1;
}
else
{
    // 你不符合这个条件的时候,就执行语句块2
    语句块2;
}

分层结构:

if(表达式1)
{
    语句块1;
}
else if(表达式2)
{
    语句块2;    
}
else
{
    // 都不符合条件
    语句块3;
}

圆角矩形-起止 菱形-判断 矩形-处理 平行四边形-输入输出

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int a, b;
    scanf("%d %d", &a, &b);
    if(a > b)
    {
        printf("a > b\n");
    }
    else if(a == b)
    {
        printf("我们都一样\n");
    }
    else
    {
        printf("a < b\n");
    }
    
    return 0;
}

嵌套结构:

if(表达式1)
{
    if(表达式2)
    {
        语句块1.1;
    }
    else
    {
        语句块1.2;
    }
}
else
{
    语句块2;
}

总结:
    1) if后面可以没有else,但是 else 前面去须有if
    2) if和else后面的{}可以省略,但是只能匹配后面一条语句
    
    int a;
    scanf("%d", &a);
    if(a > 10)
        a++;
    printf("%d\n", a);
    else
        printf("on Ok\n");
    
    // 会报错,省略大括号之后,符合条件的话只执行 a++ 这一条语句

练习:

实现大小写转换(用getchar、putchar实现)

输入大写字母输出小写字母,

输入小写字母输出大写字母,

输入的不是字母,提示输入错误。

##
















#

switch_case

基本结构:
switch(变量或表达式)
{
    case 常量1: 语句块1; break;
    case 常量2: 语句块2; break;
    case 常量3: 语句块3; break;
    ...
    case 常量n: 语句块n; break;
    // 如果以上常量都不符合的情况下
    // 就执行 default 后面的语句块
    default: 语句块 n+1;
}

执行顺序:
判断switch后面的表达式的结果,和case后的常量相匹配,如果匹配成功,就执行对应的语句块,如果没有匹配成功就执行default后面的语句块,遇到break结束


#include <stdio.h>

int main(int argc, char const *argv[])
{
    int a;
    scanf("%d", &a);
    switch (a)
    {
    case 1: printf("a = %d\n", a); break;
    case 2: printf("a = %d\n", a); break;
    case 3: printf("a = %d\n", a); break;

    default: printf("other\n"); break;
    }

    return 0;
}

注意:
1. 表达式不能是浮点型或字符串
2. case后面的break可以省略,但是省略时会顺序执行,直到遇到break结束;

练习:

从终端输入一个学生的成绩,判断学生成绩,打印成绩级别

【90 - 100】 A

【80 - 89】 B

【70 - 79】 C

【60 - 69】 D

< 60 sorry you lost

从终端输入3个整数;从大到小排序

#















#

循环语句

for循环

1. 基本结构
// for循环后面不要使用 分号
for(表达式1; 表达式2; 表达式3)
{
    语句块;
}

表达式1:赋初值
表达式2:循环的终止条件
表达式3:增值减值语句

执行顺序:
首先执行表达式1进行赋值,然后判断表达式2是否成立,如果成立就进入循环执行语句块
再执行表达式3进行增值或减值语句然后继续判断表达式2是否成立,直到表达式2不成立退出循环

#include <stdio.h>

int main(int argc, char const *argv[])
{
    for (int i = 1; i <= 10; i++)
    {
        printf("您已重生%d次\n", i);
    }
    
    return 0;
}

2. 嵌套结构
for(表达式1; 表达式2; 表达式3)
{
    for(表达式4; 表达式5; 表达式6)
    {
        语句块7;
    }
}

执行顺序:
首先执行表达式1,判断它符不符合表达式2的条件。
符合进入内部的循环,执行表达式4,然后判断表达式5是否成立,
执行语句块,表达式6执行占增值或减值语句,
继续判断表达式5是否成立,直到表达式5不成立了,
来到表达式3,执行增值或减值语句,
继续判断表达式2是否成立,直到表达式2不成立,循环结束

执行顺序:124576(直到5不成立) 324576(直到表达式2不成立) 循环结束

int i, j;
    for (i = 1; i <= 10; i++)
    {
        for (j = 1; j <= 10; j++)
        {
            printf("%d.%d,  ", i, j);
        }
        printf("\n");
    }
基本结构的变形

变形一:

int i = 0;

for(;表达式2; 表达式3)

{

        语句块;

}

变形二:

int i = 0;

for(; 表达式2; )

{

        语句块;

        表达式3

}

变形三

int i = 0;

for(; ;) // 死循环

{

        if(表达式2)

{

        语句块;

        表达式3;

}

else

{

        break;

}

}

练习:

打印以下图案:要求行数从终端输入。

输入:5
解题思路:用for循环嵌套实现外层循环控制行数,内层循环控制每行个数。

// 结果
*
**
***
****
*****
#















#

 

while循环

定义循环变量并赋值;
while(判断条件)
{
    语句块;
    增值或减值语句;
}

执行顺序:
首先定义循环变量并赋值,然后判断是否符合终止条件,
如果符合就进入循环执行语句块及增值减值语句,
然后继续判断,直到不成立退出循环


int i = 1, sum = 0;
while (i <= 10)  // 1-10的累加和
{
    sum = sum + i;
    i++;
}
printf("%d\n", sum);

练习:一起来找错

#include
int main()
{
	while(1>0);
	print("hello");
	return 0;
}

do_while循环

定义循环变量并赋值
do
{
    语句块;
    自增自减语句;
}while(终止条件)
先执行后判断

练习:实现 1-10的累加和
int i = 1, sum = 0;
do
{
    sum += i;
    i++;

}while(i <= 10)
printf("%d\n", sum); // 55

死循环

for(;;){};
while(1){};
while(1); // 让程序卡死在这里等待

循环控制语句

break; continue;

break:直接结束循环

continue:结束本次循环,继续下一次循环

使用场景:

使用在循环语句中,结束循环

使用时需要有判断条件

for (int i = 0; i < 5; i++)
    {
        if(i == 3)
        {
            // break;
            continue;
        }
        printf("%d\n", i);
    }

练习:

从终端上输入一个字符并在终端上输出这个字符,当输入字符为‘q’时,程序结束。

练习:

1.循环输入一个5位数,判断它是不是回文数。当输入0时循环结束。

即12321是回文数,个位与万位相同,十位与千位相同。

2. 写程序实现功能:读入两个整数(data1和data2)和一个运算符(op),计算表达式data1 op data2 的值.其中op可以为+、-、*、/四个符号中的任一种(用switch语句实现)

3. 输入任意两个数,输出两数之间(包括这两个数)偶数之和。

思路:将输入的两个数a,b中小的数a,依次加1,加到b的值,每次循环判断这个数a是否为偶数,是则累加到sum中

4. 打印99乘法表

数组

1. 概念:

具有一定顺序的若干变量的集合

2. 定义格式:

存储类型 数据类型 数组名[元素的个数]

int arr[5];

数组名:代表数组首元素的首地址,arr是地址常量,不能为左值,不能被赋值

3. 访问元素:

数组名[下标]:下标从0开始

访问第一个元素:arr[0];

访问第n个元素:arr[n-1];

注意数组越界问题

4. 特点:

1) 数组的元素数据类型相同

2) 内存连续

5. 注意:

1) 数组的数据类型就是数组元素的数据类型

2) 数组名要符合标识符命名规则

3) 在同一个函数中,数组名不要与变量名相同

4) 下标重0开始,到n-1 结束

6. 分类:

一维数组、二维数组

一维数组

只有一个下标的数组

1. 格式:

存储类型 数据类型 数组名[元素个数];

2. 访问元素:

数组名[下标],下标是从0开始

3. 数组名:

数组的首地址

4. 初始化:

4.1. 全部初始化:

int arr[5] = {1, 2, 3, 4, 5};

int arr[5] = {1, 2, 3, 4, 5};

printf("%d\n", arr[0]); // 1

printf("%d\n", arr[2]); // 3

printf("%d\n", arr[4]); // 5

4.2. 部分初始化:

int arr[5] = {1, 2}; // 1 2 0 0 0 初始化的部分照常赋值,未初始化部分值为0

未初始化的部分为0

4.3. 未初始化:

随机数,需要单个元素赋值

int arr[5]; // 这样就是随机值

int arr[5]; // 我们只能进行单个赋值

arr[0] = 1;

arr[1] = 2;

arr[2] = 3;

5. 定义空数组

5.1. 全部初始化:

int arr[5] = {0, 0, 0, 0, 0};

5.2. 部分初始化:

int arr[5] = {0};

5.3. 空数组:

int arr[5] = {};

6. 引用

6.1. 先定义后引用
6.2. 每次只能引用一个数组元素 arr[i],如果想引用所有元素可以循环遍历

int arr[5] = {1, 2, 3, 4, 5};

for (int i = 0; i < 5; i++){

printf("%d\n", arr[i]);

}

6.3. 引用时防止数组越界,虽然有时编译器不会报错

printf("%p\n", &arr[i]);

6.4. 打印数组元素的地址用 %p 格式

7. 内存分配:

一一对应

8. 数组遍历

把循环变量作为数组的下标,用 for 循环遍历

int arr[5] = {};
int i; // 循环变量
for(i = 0; i < 5; i++)
{
    scanf("%d", &arr[i]);
}
for(i = 0; i < 5; i++)
{
    printf("%d", arr[i]);
}
printf("\n");

printf("%d\n", arr[5]);  // 数组越界,错误

9. 数组大小:

int arr[5]; // 20

double b[2]; // 16

char c[32]; // 32

1. 数组元素个数 * 数据类型大小

2. sizeof(数组名)

printf("%d\n", sizeof(arr)); // 20 字节

计算元素的个数:

1. sizeof(数组名) / sizeof(数据类型)

2. 直接观察

练习:

计算斐波那契数列前15项并逆序输出

1 1 2 3 5 8 13 21 .....

int a[5] = {1, 2, 3, 4, 5};

for(int i = 0; i < 5; i++)

printf("%d\n", a[i]);

a[5] = {0}; // 越界了

int a[5] = {0}; // 这样也不行

a[0] = 0; // 这样可以,就是太麻烦了

清零函数

1. bzero

#include <strings.h>

void bzero(void *s, size_t n);

功能:将空间设置为0

参数:s:要清空的空间的首地址

n:字节大小

返回值:无

#include <stdio.h>
#include <strings.h>

int main(int argc, char const *argv[])
{
    int arr[5] = {1, 2, 3, 4, 5};
    bzero(arr, sizeof(arr));
    for (int i = 0; i < 5; i++)
    {
        printf("%d\n", arr[i]);
    }

    return 0;
}

2. memset

#include <string.h>

void *memset(void *s, int c, size_t n);

功能:将内存空间设置为0

参数:s:要清空的空间的首地址

c:要设置的值,设置为0

n:字节大小

返回值:要清空的空间的首地址

#include <stdio.h>
#include <string.h>

int main(int argc, char const *argv[])
{
    int arr[5] = {1, 2, 3, 4, 5};
    memset(arr, 0, sizeof(arr));
    for (int i = 0; i < 5; i++)
    {
        printf("%d\n", arr[i]);
    }

    return 0;
}

字符数组

字符数组可以存放字符串

1. 概念:

元素的数据类型为字符型的数组

2. 形式:

char a[] = {'a', 'b', 'c'}; // 逐个字符的赋值,sizeof(a) == 3

char b[] = {"hello"}; // 用字符串赋值,sizeof(b) == 6

// 因为字符串后面会默认补一个\0,所以是6

char c[] = "hello"; // 用字符串赋值,sizeof(b) == 6

char str[32] = "hello"; // szieof(str) == 32

char d[]; // 这样是不可以的,会报一个没有数组大小

char d[] = {}; // 大小是0,随便放一个东西就会越界

注意:字符串赋值常常省略数组的长度,需要注意数组越界问题

3. 字符数组输入输出

输入

char s[32] = {};

1) scanf("%s", s);

*输入字符串不能含有空格*,因为scanf输入字符串遇到空格或者 \n 都会认为字符串输入结束,空格后面就不能再存放到数组里面

如果需要输入空格就按以下格式输入

scanf("%[^\n]", s); // 直到遇到 \n 才结束

2) 循环遍历

for(int i = 0; i < 5; i++)

{

scanf("%c", &s[i]);

}

3) gets

#include <stdio.h>

char *gets(char *s);

功能:从终端获取字符串

参数:s:目标字符数组的首地址

返回值:目标字符数组的首地址

gets(s); // gets在输入的时不关心数组越界问题,使用时会报警告

char s[32] = {};

gets(s);

printf("%s\n", s);

输出

1) printf("%s\n", s);

2) 循环遍历

for(int i = 0; i < 32; i++){

printf("%c", s[i]);

}

3) puts

#include <stdio.h>

int puts(const char *s);

功能:向终端输出字符串

参数:s:要输出字符数组的首地址

返回值:输出字符的个数

// 如果不需要返回值直接调用函数就可以了

puts(s);

char s[32] = {};

gets(s);

puts(s);

例题:判断对错

char s[10] = {};

s[10] = "hello"; // 错误,数组越界

s = "hello"; // 错误,s是地址常量,不能为左值

strcpy(s, "string"); // 正确

练习:

将一串字符串进行倒置,例如:char buf[32]=”hello”;//olleh

int n;

for(n = 0; buf[n] != '\0', n++); // 计算元素的个数

计算字符串的实际长度

1. for循环遍历数组,直到 \0 为止

for (n = 0; buf[n] != '\0'; n++);

2. strlen

#include <string.h>

size_t strlen(const char *s);

功能:计算字符串的实际长度(不包含 \0)

参数:s:要计算字符串的首地址

返回值:字符串的实际长度

char buf[32] = {"hello"};

int num = strlen(buf);

printf("%d\n", num); // 5

sizeof(buf); // 32

char buf[] = {"hello"};

int num = strlen(buf);

printf("%d\n", num); // 5

sizeof(buf); // 6

sizeof和strlen的区别?

// 本质上

1. sizeof 是关键字,strlen是函数

// 功能上

2. sizeof是计算数据所占内存空间大小

strlen计算字符串的实际长度(字符的数量,不包括结束标志'\0')

// 使用时

3. sizeof计算包括 \0,strlen是不包含 \0;计算字符串长度时(元素个数省略的情况下)sizeof 比 strlen大1;

练习:实现字符串大小写转换

作业:

2. 在终端输入大写字母、小写字母、空格、数字,分别在终端输出他们的个数

3. 猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个,第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了。求第一天共摘了多少。

冒泡排序

两两比较,第j个和 j+1个比较

int a[5] = {5, 4, 3, 2, 1};

第一轮: i = 0 n个数:比较n-1轮,每一轮交换的次数是 n - 1次开始依次递减的

4 5 3 2 1

4 3 5 2 1

4 3 2 5 1

4 3 2 1 5

第二轮: i = 1

3 4 2 1 5

3 2 4 1 5

3 2 1 4 5

第三轮: i = 2

2 3 1 4 5

2 1 3 4 5

第四轮: i = 3

1 2 3 4 5

练习:将10个数进行冒泡排序

选择排序

n 个数:先找出最小值的下标暂存,选择出最小的值与arr[i] 个数交换

排序过程:

1. 首先通过n-1次比较,从n个数中找出最小值的下标,将它与第一个数交换,第一轮选择排序,结果最小值被放在第一个元素的位置上

2. 再通过 n-2 次比较,从剩余的 n-1 个数中找出最小值的下标做记录,将它与第二个数交换,第二轮的排序

3. 重复上述过程,共经过 n-1 轮排序后,排序结束

二维数组

1. 格式

存储类型 数据类型 数组名[行数][列数]

int arr[2][3];

2. 访问元素:

数组名[行下标][列下标];(下标从0开始)

arr[0][0]:第一行第一列的元素

arr[1][2]:第二行第三列的元素

行下标和列下标都不能越界

行数可以省略,列数不能省略

int a[][3] = {1, 2, 3, 4, 5, 6};

3. 数组的元素个数

行数*列数

二维数组的大小 / 数据类型的大小

4. 二维数组的大小

sizeof(数组名)

数据类型的大小*行数*列数

5. 数组名

arr:第一行首地址

arr+1:第二行首地址

arr+n:第n+1行首地址

6. 初始化:

a) 全部初始化:

int arr[2][3] = {1, 2, 3, 4, 5, 6}; // 顺序赋值

printf("%d %d %d\n", arr[0][0], arr[0][1], arr[0][2]); // 1 2 3

printf("%d %d %d\n", arr[1][0], arr[1][1], arr[1][2]); // 4 5 6

int arr[2][3] = {

{1, 2, 3},

{4, 5, 6}

}; // 按行赋值

b) 部分初始化:未被初始化的元素值为0

int arr[2][3] = {1, 2, 3, 4}; // 顺序赋值 1 2 3 4 0 0

int arr[2][3] = {{1, 2},{4, 5}}; // 按行赋值 1 2 0 4 5 0

c) 未初始化:随机值,需要单独赋值

int arr[2][3];

A

C

// B

for(i=0;i<3;i++)
{
	for(j=0;j<=i;j++)
    {
	    a[i][j]=i*j;
    }
}
printf("%d\n",a[][]);

a[0][0]=0;
a[1][0]=0;a[1][1]=1;
a[2][0]=0;a[2][1]=2;a[2][2]=4;

7. 内存分配

// a 和 a[0] 并不完全相同,级别不同,后面会讲,数值上是一样的,级别不一样
// a 是行地址
// a[0] 是列地址

// a 表示第一行的首地址
// a+1 表示第二行的首地址
// a[0] 表示第一行第一列的地址
// a[1] 表示第二行第一列的地址

8. 二维数组遍历

for循环嵌套,外层行数,内层列数

int a[m][n] = {};
for(int i = 0; i < m; i++)  // 行下标
{
    for(int j = 0; j < n; j++)  // 列下标
    {
        scanf(); 或者 printf();
    }
}

// 写一个 for循环嵌套 a[2][3] 从终端输入,并输出,也可以直接初始化,从终端输出

练习3:有一个3x4的矩阵(元素值不相同),要求输出其中最大值以及它的行号和列号

练习:打印杨辉三角形的前十行

1

1 1

1 2 1

1 3 3 1

1 4 6 4 1

1 5 10 10 5 1

1 6 15 20 15 6 1

if(i == j || j == 0)

a[i][j] = 1;

a[i][j] = a[i-1][j] + a[i-1][j-1]

指针

指针的优点:

\1. 使程序更简洁、紧凑、高效

\2. 有效的表达更复杂的数据结构

\3. 动态分配内存

\4. 得到多于一个数的函数返回值

1. 概念

地址:内存中每个字节单位都有一个编号(门牌号)

指针:指针就是地址

指针变量:用于存放地址的这种变量就叫指针变量

2. 格式:

存储类型 数据类型 *指针变量名

int *p; // 定义了一个指针变量p

例子:

int num = 5;

int *p = &num;

char ch = 'c';

char *q = &ch;

3. 指针操作符:

&:取地址符,取变量的地址

*:取内容,取地址里面的内容

*&a == a; // *和&都是单目运算符,互逆运算

&*a; // 运算符的优先级 // a是变量就是错的,a是地址就是对的

4. 初始化:

指针变量在使用前不仅要定义还要初始化,未初始化的指针变量不能随便使用,会产生野指针

4.1. 将普通变量的地址赋值给指针变量

int a = 10;

1) int *p = &a; // 在定义的同时赋值

2) int *p = NULL;

p = &a; // 先定义后赋值

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int a = 10;
    int *p = NULL;
    p = &a;
    printf("%d %d\n", a, *p); // 打印a的值  10 10
    printf("%p %p\n", &a, p); // 打印a的地址

    *p = 3;  // 可以通过*p改变指向的内容
    printf("%d %d\n", a, *p); // 打印a的值  10 10
    printf("%p %p\n", &a, p); // 打印a的地址
    return 0;
}

练习:

2. 键盘输入10个数,输出个位数是奇数或者十位数是偶数的所有数

3. 键盘输入数值 按照个位数升序的顺序排序

 4. 初始化

4.2. 将数组的首地址赋值给指针变量

char str[10] = "hello";

char *p = str; // 指针指向了数组的首地址,即指向了字符 'h'

char str[10] = "hello";
    char *p = str;
    printf("%p %p\n", p, str);
    printf("%c %c\n", *p, *str);
4.3. 将指针变量里面保存的地址赋值给另一个指针变量

float a =1.3;

float *p = &a;

float *q = p;

5. 指针运算

5.1. 算术运算

char str[32] = "hello";

char *p = str;

// 加一,不是加了一个字节,而是一个数据单位

p++; // 指针向高地址方向移动一个数据单位,指针指向发生变化

p--; // 指针向低地址方向移动一个数据单位,指针指向发生变化

例子:

int *p; p++; // 移动4个字节

double *p; p++; // 移动8个字节

char str[10] = "hello";
    char *p = str;
    printf("%p %p\n", &str[0], &str[1]);
    p++;
    printf("%p\n", p);
    printf("%c %c\n", *p, *str);

p+n; 向高地址方向访问第n个数据的地址,指针指向不发生变化

p-n; 向低地址方向访问第n个数据的地址,指针指向不发生变化

偏移了多少地址(字节) = n * sizeof(数据类型)

两个地址之间的差 == 两个地址之间相隔的元素个数

q - p = 之间相隔的元素个数

int m = 100;
    double n = 200;
    int *p1 = &m;
    int *p2 = p1 + 2;
    double *q1 = &n;
    double *q2 = q1 + 2;
    printf("p1=%p p2%p\n", p1, p2);
    printf("p2 - p1 = %d\n", p2-p1);
    printf("q1=%p q2%p\n", q1, q2);
    printf("q2 - q1 = %d\n", q2-q1);
5.2. 关系运算

> < == !=

指针之间的关系运算比较的是它指向地址的高低

指向高地址的指针大于指向低地址的指针

char str[32] = "hello";

char *p1 = &str[1];

char *p2 = &str[3];

p2 > p1;

注意:(同一个数组之间进行比较)

指向不同类型数组的指针进行关系运算时没有意义,

指向不同区域的指针的关系运算也没有意义

6. 指针的大小

int a = 5;

int *p1 = &a; // 4

short b = 2;

short *p2 = &b; // 4

double c = 1.11;

double *p3 = &c; // 4

double *p4 = NULL; // 4

printf("%d\n", sizeof(p4));

32位操作系统:指针大小为4字节

8位16进制表示,4字节

64位操作系统:指针大小为8字节

16位16进制表示,8字节

总结:

1. 32位操作系统:指针大小为4字节,64位操作系统,指针大小为8字节

2. 内存地址是固定,但是但是变量的地址不固定(栈区随机分配变量)

3. 指针类型根据指针指向空间的数据类型

练习:

编写一个程序实现功能:将字符串“Computer Science”赋值给一个字符数组,然后从第一个字母开始间隔的输出该字符串,用指针完成。结果:Cmue cec

Segentation fault (core dumped

产生原因:

访问不存在的内存地址、访问系统保护的地址、访问只读的内存地址、

空指针废弃(eg:malloc 与 free释放后,继续使用)、栈堆溢出

内存越界(数组越界、变量类型不一致等)

指针修饰

1. const 常量化

1) const int a =10;

int const a = 10;

a = 20; // 错,a的值不能改变,可以通过指针间接修改

// 因为 const 没有修饰 *p,修饰的是a

int *p = &a;

*p = 20; // 可以

2) const int *p; // 修饰 *p,指针指向的内容不能修改,指针指向可以修改

int const *p;

int a = 10;

const int *p = &a;

2.1) *p = 20; // 错误,因为 *p 被修饰

2.2) int b = 20;

p = &b; // 正确

3) int *const p; // 修饰 p,指针指向不能被改变,指针指向的内容可以修改

int a = 10;

int b = 20;

int *const p = &a;

3.1) *p = 20; // 正确

3.2) p = &b; // 错误,因为修饰的是 p,指针指向不能改变

练习:

2. 字符串倒置(用指针实现) 如:hello->olleh

思路:定义两个指针分别指向字符串的开头和结尾,前面的指针向后走,后面的指针向前走

3. 将字符串转换成整型数字输出。用指针实现

要求:字符串为0-9组成,输出数据为一个整形数

Eg:char s[10]=”123”;printf(“%d\n”,num); //num=123;

4) 修饰函数的参数

2. void

void a; // 不允许修饰变量

void *p; // p 任意类型的指针

使用场景:函数参数或者函数返回值

注意:通过void类型的指针进行取内容的时候,需要对地址进行强转

转换方式:void *p = NULL; 强转:(int *)p 取内容:*(int *)p

int a = 10;

void *p = NULL;

// (int *)p = &a; // 错误 对指针进行类型强转需要在赋值右面

p = &a;

int *q = (int *)p;

printf("%d %d\n", *q, *(int *)p); // 10 10

1. 若有以下说明语句:int a[12]={1,2,3,4,5,6,7,8,9,10,11,12};char c='a', d, g;则数值为4的表达式是()。

A)a[g-c] B)a[4] C)a['d'-'c'] D) a['d' - c]

2. 假设int型变量占两个字节的存储单元,若有定义:int x[10]={0,2,4};则数组x在内存中所占字节数为()。

A)40 B)6 C)12 D) 20

3. 若给出定义:char x[]=”abcdefg”;char y[]={‘a’,’b’,’c’,’d’,’e’,’f’,’g’};则正确的叙述为()。

A) 数组x和数组y等价 B) 数组x和数组y的长度相同

C) 数组x的长度大于数组y的长度 D) 数组y的长度大于数组x的长度

4. 有以下程序,执行后输出结果是()。

#include<stdio.h>

int main()

{

int m[][3]={1,4,7,2,5,8,3,6,9};

int i,j,k=2;

for(i=0; i<3; i++)

{

printf("%d ",m[k][i]);

}

}

A 4 5 6 B) 2 5 8 C) 3 6 9 D) 7 8 9

5. 若有以下定义语句:char s[10];s=”abcd”;printf(“%s\n”,s);则运行结果是()。

A) 输出 abcd B) 输出a C) 输出 ab cd D) 编译不通过

6. 若有以下程序段,该程序段的输出结果是()。

char str[]=“ab\n\012\\\””;

printf(“%d”,strlen(str));

A) 3 B) 7 C) 6 D) 12

大小端

在计算机进行超过1字节数据进行存储时,会出现存储数据顺序不同的情况即大小端存储

Big-Endian(大端字节序)大端:在低地址存放高字节数据,高地址存放低字节数据

Little-Endian(小端字节序) 小端:在低地址存放低字节数据,在高地址存放高字节数据

举例:存储数据:0x12345678, 起始地址:0x4000

0x4000 0x4001 0x4002 0x4003

大端: 0x12 0x34 0x56 0x78

小端: 0x78 0x56 0x34 0x12

int a = 0x12345678;
    char b;
    b = (char)a;
    printf("%#x\n", b);
// 电脑是小端,网络是大端
    // 电脑向网络传输东西,数据要从小端转成大端,传出去
    // 网络像电脑传输东西,数据要从大端转成小端,接收回来

二级指针

一级指针:存放变量的地址

二级指针:存放一级指针的地址(指针变量的地址)

格式:存储类型 数据类型 **指针变量名

int a = 10;

int *p = &a;

int **q = &p;

访问a的值:

a *p **q

访问a的地址:

&a p *q

访问 p的地址

&p q

  • 24
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值