「声明和定义的区别:」
-
声明变量不需要建立存储空间,如:
extern int a
; (使用extern
关键字) -
定义变量需要建立存储空间,如:
int b
; -
从广义的角度来讲声明中包含着定义,即定义是声明的一个特例,所以并非所有的声明都是定义:
①int b
它既是声明,同时又是定义;
②对于extern int b
来讲它只是声明不是定义; -
一般的情况下,把建立存储空间的声明称之为“定义”,而把不需要建立存储空间的声明称之为“声明”。
sizeof关键字
sizeof
不是函数,所以不需要包含任何头文件,它的功能是计算一个数据类型的大小,单位为字节; sizeof
的返回值为 size_t
;size_t
类型在32位操作系统下是 unsigned int
,是一个无符号的整数;
#include <stdio.h>
int main(int argc, char const *argv[])
{
//数据类型的作用: 告诉编译器,分配此类型的变量需要多大的空间
printf("sizeof(char) = %un",sizeof(char));
int a;
printf("sizeof(a) = %dn",sizeof(a));
size_t len = sizeof(long);
printf("sizeof(long) = %un",len);
return0;
}
输出:
sizeof(char) = 1
sizeof(a) = 4
sizeof(long) = 8
char数据类型-char的本质就是一个1字节大小的整型
-
内存中没有字符,只有数字; -
一个数字,对应一个字符,这种规则就是 ascii
; -
使用字符或数字给字符变量赋值是等价的; -
字符类型本质就是1个字节大小的整形; -
字符变量实际上并不是把该字符本身放到变量的内存单元中去,而是将该字符对应的 ASCII 编码放到变量的存储单元中。
测试:
#include <stdio.h>
int main(int argc, char const *argv[])
{
char ch = 'a';
printf("ch[c] = %c, ch[d] = %dn",ch, ch);
char ch2 = 97;
printf("ch2[c] = %cn", ch2);
printf("ch2 - 32 = %cn",ch2 - 32);
return0;
}
输出:
ch[c] = a, ch[d] = 97
ch2[c] = a
ch2 - 32 = A
以及注意转义字符:
转义字符简单测试:
#include <stdio.h>
int main(int argc, char const *argv[])
{
char ch = 'r';
printf("abcdddd%cefgn",ch);
ch = 'b';
printf("12%c345n",ch);
ch = ' ';
printf("%dn",ch); // 打印' '的对应数字
// 8进制转义字符
printf("%dn", '123'); //8进制123 --> 对应10进制83
printf("%dn", 'x23'); //16进制23 --> 对应10进制35
// ' '和0等价
printf("%d,%dn",' ',0);
return0;
}
输出:
efgdddd
1345
32
83
35
0,0
浮点数不准确、类型限定符
-
浮点数不准确:
#include <stdio.h>
int main(int argc, char const *argv[])
{
float a = 100.9;
printf("a = %fn",a);
return 0;
}
输出:
a = 100.900002
原因还是计算机按照二进制
存储。
-
类型限定符:
字符的输入问题
#include <stdio.h>
int main(int argc, char const *argv[])
{
char ch1;
printf("请输入字符:");
scanf("%c",&ch1);
printf("ch1 = %cn",ch1);
char ch2;
printf("请输入字符:");
scanf("%c",&ch2);
printf("ch2 = %cn",ch2);
//输出ch2的ascii码
printf("ch2[d] = %dn",ch2);
return0;
}
输入输出演示:
这个程序要特别注意:
-
当我们输入完一个字符时,按下回车,会直接结束程序; -
因为第二个字符在按下回车的时候已经输入完成了,也就是 ch2 = 'n'
;而'n'
的ascii
码为10;
处理上面的问题,可以使用另一个字符变量过滤掉n
,也可以使用getchar()
来过滤一个字符:
#include <stdio.h>
int main(int argc, char const *argv[])
{
char ch1;
printf("请输入字符:");
scanf("%c",&ch1);
printf("ch1 = %cn",ch1);
//为了处理上面的问题,可以自己用scanf处理这个回车
char tmp;
//scanf("%c",&tmp); //或者使用下面的方法输入一个字符
// tmp = getchar(); //或者也可以直接调用getchar()即可
getchar();
char ch2;
printf("请输入字符:");
scanf("%c",&ch2);
printf("ch2 = %cn",ch2);
//输出ch2的ascii码
printf("ch2[d] = %dn",ch2);
return0;
}
运算符以及优先级
「运算符优先级: 」
另外,注意 逻辑判断中的 短路原则。
类型转换
-
隐式转换: 编译器内部自动转换; -
强制类型转换:把表达式的运算结果强制转换成所需的数据类型。 -
浮点型打印说明: 不要以为指定了打印的类型就会自动转换,必须要强制转换; -
转换原则: 数据类型小的往大的转换;
#include <stdio.h>
int main(int argc, char const *argv[])
{
printf("------------隐式转换-----------n");
//隐式转换
double a;
int b = 10;
//编译器内部自动转换,在第10行自动转换,其他地方b还是int
a = b;
printf("a = %lfn",a);
printf("------------强制类型转换-----------n");
//强制类型转换
double c = (double)1/2; //强制将1转换成double
printf("c = %lfn",c);
printf("sizeof(int) = %un",(unsignedint)sizeof(int));
printf("------------浮点型打印说明-----------n");
//浮点型打印说明
int d = 11;
printf("d[wrong] = %lfn",d); //以为指定了%lf就会转换成浮点数,其实是错的
printf("d[right] = %lfn",(double)d); // 正确的打印是要强制类型转换的
double e = 88.14;
printf("e[wrong] = %dn",e);
printf("e[right] = %dn",int(e));
printf("-------------转换原则----------n");
//转换原则: 数据类型 小的往大的 转换
int g = 129;
char h = 111;
//g = (int)h; // 这个是可以转换的
//printf("g = %dn",g);
h = (char)g; //这个转换是出错的,h会变成一个负数
printf("h = %dn",h);
return0;
}
输出:
------------隐式转换-----------
a = 10.000000
------------强制类型转换-----------
c = 0.500000
sizeof(int) = 4
------------浮点型打印说明-----------
d[wrong] = 0.000000
d[right] = 11.000000
e[wrong] = 1519177328
e[right] = 88
-------------转换原则----------
h = -127
数组、字符串、函数
数组初始化的几种方式
#include <stdio.h>
int main(int argc, char const *argv[])
{
int arr1[5] = {1,2,3,4,5}; //数组的定义需要{},只有在定义的时候才能初始化
int arr2[5];
//arr2 = {1,2,3,4,5}; //err 这个是错误的
//数组全部元素初始化为 某个值
int arr3[5] = {0};
//如果定义的同时 初始化,第一个[]内可以不写内容
int arr4[] = {1,2,3,4,5}; //编译器会根据用户初始化的元素来确定数组的大小
//int arr4[]; //err //必须初始化的时候才能省略
int arr5[][4] = {0,1,2,3,4,5,6,7,8,9,10,11}; //第一个可以省略
return0;
}
-
数组的名字代表着数组的首地址,以及使用 sizeof
来求数组长度的方法;
#include <stdio.h>
int main(int argc, char const *argv[])
{
printf("------------一维数组------------n");
int arr[10];
//1. 数组名是数组首元素地址
printf("arr = %p, &arr[0] = %pn", arr, &arr[0]); //两个是一样的
//2. 测试数组总的字节大小 : sizeof(数组名) 10 * 4 = 40
printf("sizeof(arr) = %un",sizeof(arr));
//3. 得到数组长度 数组总大小/每个元素大小 (常用)
int len = sizeof(arr)/sizeof(arr[0]);
printf("len(arr) = %dn",len);
printf("------------二维数组------------n");
int arr2[5][10];
// 1. 数组名是常量,不能修改
// a = 10; //err
//2. sizeof(数组名),测数组的总大小 5*int[10] = 5*4*10
printf("sizeof(arr2) = %un",sizeof(arr2));
//3. 求行数
int n = sizeof(arr2)/sizeof(arr2[0]);
printf("行数 = %dn",n);
//4. 求列数
int m = sizeof(arr2[0])/sizeof(arr2[0][0]);
printf("列数 = %dn",m);
//5. 总个数
printf("总个数 = %dn",sizeof(arr2)/sizeof(arr2[0][0]));
return0;
}
输出:
------------一维数组------------
arr = 0x7ffc86eac190, &arr[0] = 0x7ffc86eac190
sizeof(arr) = 40
len(arr) = 10
------------二维数组------------
sizeof(arr2) = 200
行数 = 5
列数 = 10
总个数 = 50
可以看出arr
和arr[0]
的地址是一样的。
字符数组与字符串
-
C语言中没有字符串这种数据类型,可以通过 char
的数组来替代; -
字符串一定是一个 char
的数组,但char
的数组未必是字符串; -
数字 0
(和字符‘ ’
等价)结尾的char
数组就是一个字符串,但如果char
数组没有以数字0
结尾,那么就不是一个字符串,只是普通字符数组,所以字符串是一种特殊的char
的数组。
#include <stdio.h>
int main(int argc, char const *argv[])
{
// 1. c语言没有字符串类型,用字符数组模拟
char str[10];
// 2. 字符串一定是字符数组,字符数组不一定是字符串
// 3. 如果字符数组以' '(0)结尾,就是字符串
char str2[] = {'a', 'b', 'c'};//字符数组 --> 注意这里[]内没有指定数字
char str3[10] = {'a', 'b', 'c', ' '}; //字符串
char str4[10] = {'a', 'b', 'c', 0}; //字符串
return0;
}
原文始发于微信公众号(泷羽sec-心安):C语言笔记3
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论