C1数据类型,常量变量,输入输出,运算符,if/switch/循环,/数组,指针,/结构体,文件操作,/编译预处理,gdb,makefile,线程
Posted 码农编程录
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C1数据类型,常量变量,输入输出,运算符,if/switch/循环,/数组,指针,/结构体,文件操作,/编译预处理,gdb,makefile,线程相关的知识,希望对你有一定的参考价值。
文章目录
- 1.数据类型:单双引号,char(1B),int/float(32位系统,大小一样4B,但存储方式不同),double(8B),long double(12B)
- 2.常量和变量:memset,const
- 3.输出和输入:gets获取一行数据,并作为字符串处理
- 4.运算符:前先加1,sizeof
- 5.if/switch/循环:上下,else if
- 6.数组:存数据类型相同的数据,数组下标越界导致core dump段错误
- 7.指针:指针数组:这个数组的所有元素都是指针类型。数组指针:这个指针存放着一个数组的首地址
- 8.main函数的参数:main函数的参数是从命令提示符下执行程序时传入
- 9.static/extern/堆内存:realloc扩建
- 10.动静态库:.a,指定.so,LD_
- 11.结构体:struct,memcpy,memset
- 12.文件操作:FILE结构体,fprint/fgets,fwrite/fread,ftell/rewind/fseek,fflush
- 13.编译预处理:C源程序 - 编译预处理【对预处理指令即以#开头指令和特殊符号进行处理,删除程序中注释和多余空白行】- 编译
- 14.gdb调试:set args,b/r,n/s
- 15.makefile文件:依赖文件功能
- 16.多线程:pthread_create(),查看线程top -H,ps -xH | grep
1.数据类型:单双引号,char(1B),int/float(32位系统,大小一样4B,但存储方式不同),double(8B),long double(12B)
编译器(compiler)与解释器(interpreter)
:编译型语言
像C/C++/golang/rust等都会用到编译器,并且都是AOT(ahead of time)预先编译,编译将源码编译成机器码生成二进制文件,可直接运行该文件,因为是机器码,所以运行效率很高,缺点是不够灵活,改代码的话要重新编译,此外平台依赖严重,linux平台编译出来的二进制文件无法在windows运行,跨平台还需借助交叉编译。
解释型语言
像python/js/php等使用解释器逐行解释,不需要生成二进制文件,灵活如线上php系统,改了代码功能直接生效,但解释型语言运行效率低。还有一些语言本身是用解释器在运行,但在运行时使用了编译器进行JIT(just in time)实时编译如java,是半解释半编译型语言,JIT将运行到的代码块在运行时编译成机器码,既可保证跨平台性,又能使热代码高效运行。
app可直接调os接口,也可以调c库,c库再去调os接口。一个程序只有一个main函数。#include
:包含其他文件预处理指令。main()
:这个是最简单的C程序。<stdio.h>头文件包含printf。yum -y install gcc,yum install gcc-c++。
gcc main.c int_sum.c float_sum.c
-o(output) main -Wall
(显示所有警告) -I../include
(-I后面没空格,不加-I就在main.c中指定头文件的相对路径)。gcc main.c -o main -Wall
-I../include
-L../lib
-lsum
(有库文件/lib/ibsum.so就只要main.c就行)。
1.基本类型
:字符型(char)
:描述单个字符,用单引号包含起来,如’a’,‘A’,‘1’,'$'等,键盘能输入的英文和半角符号
都是字符。关键字char是character(字符)的简写。中文里的汉字和标点符号是两个字节,不能算一个字符
,'¥','好','。'
这些都是非法的。
整型(int)
:整数在计算机上是准确表示的,如123,500,0,-10等。关键字int是integer(整数)的简写。
浮点型(double)
:描述实数有小数位,如10.0,123.55,3459.98,-50.3,实数在计算机上一般是近似表示的。只有三种:float,double,long double。
2.字符串
:描述多个字符,用双引号
包含起来,可以是英文,数字,中文,标点符号,半角全角,空字符串都可以。
3.构造类型
:由已知的基本类型通过一定的构造方法构造出来的类型,包括数组和结构体。
4.指针类型
:指针可以指向内存地址,主要用于函数的参数传递。
浮点数不是2的0次方+2的1次方…,用下面公式。
不用管如上公式,记住:浮点数最小可识别精度和浮点数即0.1本身大小相关,而不是和float相关。
1.获取字符串的长度(strlen)
5.字符串拼接(strncat)
6.字符串比较(strcmp,strncmp)
#include <stdio.h>
#include <string.h>
int main()
char *names = "PSU";
if(strcmp(names,"PSU")==0)
puts("aaaa");
int main() // error: expected ‘)’ before string constant 少了int main()
char name_str[30];
char name_str1[30];
strcpy(name_str,"/sys/bus/i2c/devices/");
strcpy(name_str1,"17-0064");
strcat(name_str,name_str1);
printf("is : %s\\n", name_str); // /sys/bus/i2c/devices/17-0064
putchar('w');putchar('w');
printf("[%s]__%4d__[%s] %s \\n", __FILE__, __LINE__, __FUNCTION__, n->name);
8.字符串查找(strstr)
#include <stdio.h>
#include <string.h>
int main ()
char str1[15];
char str2[15];
int ret;
strcpy(str1, "abcdef");
strcpy(str2, "ABCDEF");
ret = strcmp(str1, str2);
if(ret < 0)
printf("str1 小于 str2");
else if(ret > 0)
printf("str1 大于 str2");
else
printf("str1 等于 str2");
return(0); //str1 大于 str2
#include<stdio.h>
#include<string.h>
#include <pthread.h>
#include <unistd.h>
#if 0
int main()
// int a;
// char pNum[]="0x7f";
// a=strtoul(pNum,0,16);
// printf("%d\\n",a); //127
// return 0;
char str[30] = "2030300 This is test";
char *ptr;
long ret;
ret = strtoul(str, &ptr, 10);
printf("数字(无符号长整数)是 %lu\\n", ret); // 2030300
printf("字符串部分是 |%s|\\n", ptr); // This is test
return 0;
#endif
#if 0
int a=200;
int b=100;
pthread_mutex_t lock;//互斥锁的宏
void ThreadA(void)
printf("线程A.....\\n");
pthread_mutex_lock(&lock);
a-=50; //a=a-50
sleep(5);
b+=50; //b=b+50
printf("a:%d,b:%d\\n",a,b);
pthread_mutex_unlock(&lock);
void ThreadB(void)
printf("线程B.....\\n");
sleep(1);
pthread_mutex_lock(&lock);//加锁
printf("%d\\n",a+b);
pthread_mutex_unlock(&lock);//解锁
int main(void)
pthread_t tida,tidb;
pthread_mutex_init(&lock,NULL);//建立一个互斥锁
pthread_create(&tida,NULL,(void *)ThreadA,NULL);
pthread_create(&tidb,NULL,(void *)ThreadB,NULL);//创建一个线程,1.句柄,2.线程属性,3.线程函数,4.函数的参数
pthread_join(tida,NULL);//等待一个线程结束
pthread_join(tidb,NULL);
pthread_mutex_destroy(&lock);
return 1;
// -server:~/bak$ gcc test.c -lpthread
// -server:~/bak$ ./a.out
// 线程A.....
// 线程B.....
// a:150,b:150
// 300
#endif
2.常量和变量:memset,const
1.静态数据:
永久性数据,一般存储在硬盘中,只要硬盘没坏数据都是存在的,电脑关机重启后依然存在。写程序目的就是告诉计算机如何输入,处理,传输,存储和展示数据。
2.动态数据(临时数据):
程序运行过程中,动态产生的临时数据,一般存储在内存中,软件或者电脑关闭则这些临时数据会被清除。为什么不把动态数据存放到硬盘呢?因为访问内存的速度比访问硬盘快很多倍。
3.数据大小
:(1)数据都是由二进制的0和1组成。
(2)数据都会占用空间,静态数据占硬盘空间,动态数据占内存空间。
(3)数据占用空间的最小单位是比特(bit)。一个1或者0就是一个比特,即1bit。
(4)计算机中,以字节为单位存储数据。1字节=8比特(1Byte=8bit)。
(5)1B=8bit,1KB=1024B,1MB=1024KB,1GB=1024MB…
常量:
即常数,表示固定的数据:(1)字符常量 如’6’,‘a’,‘F’(不能是中文,例如:‘男’)
(2)整数常量 如6,27,-299
(3)浮点数常量 如5.43,-2.3,5.67,6.0
(4)字符串常量 如’‘625’‘,’‘女’‘,’‘nanbc’‘,’‘西施’’
变量:
如果数据的值不确定的,或者经常需要改变,或者临时取值的,则用变量取值。常量指具体数据,变量指存数据的容器,水与水桶一样。变量使用前必须先进行声明(或定义),在内存中分配一块存储空间给变量,用于存放数据。
1.整数型,字符型,浮点型变量的定义
int ii;
//定义整数型变量,用于存放整数,关键字int,是单词integer(整数)的缩写。
char cc;
//定义字符串变量用关键字char,是单词charcter(字符)的缩写,存放字符。
double money;
//定义浮点型变量,用于存放浮点数,关键字double。
2.字符串变量的定义
C语言中没有字符串这个数据类型,而是用字符数组来表达字符串。char name[21];定义一个可以存放20字符的字符串即20个英文或10个中文。字符串不是C语言的基本数据类型
,不能用=赋值,不能用><比较大小,不能用+拼接,不能用==和!=判断两个字符串是否相等,要用函数。
3.变量的命名
变量名属于标识符,需要符合标识符的命名规范,如下:
1)变量名的第一个字符必须是字母或下划线,不能是数字和其它字符。
2)变量名中的字母是区分大小写的。比如 a 和 A 是不同的变量名,num 和 Num 也是不同的变量名。
3)变量名绝对不可以是C语言关键字。
关键字
也称为保留字,共32个,也就是说这些单词在C语言中有特别的含义,程序员不能把它用于变量或函数的命名。auto
:声明自动变量。break
:跳出当前循环。case
:开关语句分支。char
:声明字符型变量或函数返回值类型。const
:声明只读变量。continue
:结束当前循环,开始下一轮循环。default
:开关语句中的“默认”分支。do
:循环语句的循环体。double
:声明双精度浮点型变量或函数返回值类型。else
:条件语句否定分支(与 if 连用)。enum
:声明枚举类型。extern
:声明变量或函数是在其它文件或本文件的其他位置定义。float
:声明浮点型变量或函数返回值类型。for
:一种循环语句。goto
:无条件跳转语句。if
:条件语句。int
: 声明整型变量或函数。long
:声明长整型变量或函数返回值类型。register
:声明寄存器变量。return
:子程序返回语句(可以带参数,也可不带参数)。short
:声明短整型变量或函数。signed
:声明有符号类型变量或函数。sizeof
:计算数据类型或变量长度(即所占字节数)。static
:声明静态变量。struct
:声明结构体类型。switch
:用于开关语句。typedef
:用以给数据类型取别名。unsigned
:声明无符号类型变量或函数。union
:声明共用体类型。void
:声明函数无返回值或无参数,声明无类型指针。volatile
:说明变量在程序执行中可被隐含地改变。while
:循环语句的循环条件。
变量的初始化
:在main函数内部定义的变量称为局部变量,局部变量被定义后,系统不会对其初始化,必须自己写程序初始化。
多变量定义
:int ii,jj;,const是constant缩写,意思是“恒定不变的”!它是定义只读变量的关键字,或者说 const 是定义常变量的关键字。用 const定义常变量
方法很简单,就在通常定义变量时前面加 const 即可,如:const double pi = 3.1415926;
用 const 定义的变量的值是不允许改变的,即不允许给它重新赋值,即使赋相同的值
也不可以。所以说它定义的是只读变量。这也就意味着必须在定义的时候就给它赋初值,如果程序中试图改变它的值,编译的时候就会报错。
1.整数型,字符型,浮点型变量初始化
:就是赋0值,也可在定义时初始化。
int ii=0; // 定义整数型变量并初始化
char cc=0; // 定义字符型变量并初始化
double money=0; // 定义浮点型变量并初始化
也可以先定义,然后再初始化
int ii; // 定义整数型变量
char cc; // 定义字符型变量
double money; // 定义浮点型变量
ii=0; // 初始化ii为0
cc=0; // 初始化cc为0
money=0; // 初始化money为0
2.字符串变量的初始化
:对字符串变量来说,初始化就是把内容清空。
char name[21]; // 定义一个可以存放20字符的字符串
memset(name,0,sizeof(name)); // 清空字符串name中的内容
3.未初始化的变量示例
:未初始化的变量会导致在内存中可能有垃圾值。
3.输出和输入:gets获取一行数据,并作为字符串处理
数据输出:
在C语言中,有三个函数可以把数据输出到屏幕。
putchar 用于输出单个字符。
puts 输出字符串。
printf函数是格式化输出函数, 用于向屏幕输出数据,printf函数的调用方法是: printf(格式化字符串,参数列表);
1.输出描述性的文字
输出的文字用双引号包含起来,在文字最后加上\\n表示换一行,多个\\n可以换多行。
printf(“我心非席,不可卷也,我心非石,不可转也。\\n”);
以上代码将在屏幕上输出文字:我心非席,不可卷也,我心非石,不可转也。
输出文字之后,再输出一个换行。
2.输出整数
输出的整数常量或整数变量用%d表示,在参数中列出待输出的整数常量或整数变量。
printf(“我年龄是%d岁。\\n”,18);
int age=18;
printf(“我年龄是%d岁。\\n”,age);
3.输出字符
输出的字符常量或字符变量用%c表示,在参数中列出待输出的字符常量或字符变量。
printf(“我姓别是:%c。\\n”,‘x’); // 姓别:x-男;y-女
char xb=‘x’;
printf(“我姓别是:%c。\\n”,xb);
4.输出浮点数
输出的浮点型常量或浮点型变量用%lf表示,在参数中列出待输出的浮点型常量或浮点型变量。
printf(“我体重是%lf公斤。\\n”,62.5);
double weight=62.5;
printf(“我体重是%lf公斤。\\n”, weight);
5.输出字符串
输出的字符串常量或字符串型变量用%s表示,在参数中列出待输出的字符串常量或字符串变量。
printf(“我的姓名是%s。\\n”,“豫让”);
char name[21];
memset(name,0,sizeof(name));
strcpy(name, “豫让”);
printf(“我的姓名是%s。\\n”,name);
如下short是普通int的一半,d是十进制。
如下32指32字节。
scanf输入
:scanf函数是格式化输入函数, 用于向接受键盘输入的数据,用户输入数据完成后,需按回车键(Enter)结束输入。scanf函数的调用方法是: scanf(格式化字符串,参数列表)。注意,不要在scanf的格式化字符串的最后加\\n。
1.输入整数
输入整数的格式用%d表示,在参数中列出整数型变量名,用于保存输入的数据。
在输入数据之前,一般要先输出一句话提示用户。下同。
int age=0;
printf(“请输入你的年龄:”); // 提示文字不要换行,让用户在后面输入,下同。
scanf("%d",&age); // 在变量名前要加符号&,键盘输入值放入age变量中去。
2.输入字符
输入字符的格式用%c表示,在参数中列出字符型变量名,用于保存输入的数据。
char xb=0;
printf(“请输入你姓别:”);
scanf(“%c”,&xb); // 在变量名前要加符号&
3.输入浮点数
输入浮点数的格式用%lf表示,在参数中列出浮点型变量名,用于保存输入的数据。
double weight=62.5;
printf(“请输入你体重:”);
scanf(“%lf”,&weight); // 在变量名前要加符号&。
4.输入字符串
输入字符串的格式用%s表示,在参数中列出字符串变量名,用于保存输入的数据。
char name[21];
memset(name,0,sizeof(name));
printf(“请输入你姓名:”);
scanf(“%s”,name); // 注意了,变量名前不加符号&,也不要问原因,以后再介绍。
5.输入多个内容
调用一次scanf函数可以输入多个数据,注意了,与单个数据的输入不同,多个数据的输入要等全部的数据输入完成后才按回车键。
int age=0;
char xb=0;
double weight=0;
char name[21];
memset(name,0,sizeof(name));
printf("请输入你的姓名、姓别(x-男;y-女),年龄和体重,中间用空格分隔:");
scanf("%s %c %d %lf",name,&xb,&age,&weight);
// 只有name变量前没加&,其它的都加了。因为name数组名就是首地址名。
scanf函数第一个参数(格式化字符串)的格式与后面的参数列表(变量的列表)要一一对应,不能多,不能少,顺序也不能错,否则会产生意外的结果。查找头文件:man memset显示如下。man 3 printf。1,2,3去试。
4.运算符:前先加1,sizeof
||
左边的命令返回假(命令返回值 $? == 1),||
右边的命令才会被执行。这和 c 语言中的逻辑或语法功能相同,即实现短路逻辑或操作: 只要有一个命令返回真(命令返回值 $? == 0),后面的命令就不会被执行。
运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C 语言内置了丰富的运算符,并提供了以下类型的运算符:1)算术运算符 2)赋值运算符 3)关系运算符 4)逻辑运算符 5)位运算符。如下浮点数没有取余数的说法。
如下ii++,就是ii=ii+1。
=是赋值,==才是判断两个数是否相等,C语言没有(之间,中间,之内或在某范围内)的关系运算符,例如年龄在25-30岁之间,只能表达为:年龄大于等于25岁并且年龄小于等于30岁。括号中表达式会优先执行
,sizeof(指针)大小永远是8字节,如下是sizeof运算符,sizeof是C语言的关键字,发挥着运算符的作用。
它主要用来计算某一个变量在当前系统的内存中所需占用的字节数。变量的类型包括char、int、double、数组、结构体和其它自定义的数据类型。sizeof不是函数。
产生这样的疑问主要是因为sizeof的书写确实有点像函数,比如:i = sizeof(int);这样的写法,就很容易让人误以为sizeof是一个函数。sizeof有两种写法:
1.用于数据类型
sizeof使用形式:sizeof(type)
数据类型必须用括号括住。如sizeof(int)。
printf(“sizeof(int)=%d\\n”,sizeof(int)); // 输出结果:sizeof(int)=4
2.用于变量
sizeof使用形式:sizeof(var_name)或sizeof var_name
变量名可以不用括号括住。如sizeof(var_name),sizeof var_name等都是正确形式。
printf(“sizeof dd =%d\\n”,sizeof dd); // 输出结果:sizeof dd =8
printf(“sizeof(dd)=%d\\n”,sizeof(dd)); // 输出结果:sizeof(dd)=8
5.if/switch/循环:上下,else if
不要在if(判断条件)后面加分号。有;号就为空语句,下面都执行。c=(a>b)?a:b等同于两行:if(a>b) c=a;else c=b; if(0)
即0假。if(a=b)是赋值,不是判断。
当没有default时,如果所有case都匹配失败,那么就什么都不执行。char day=0,scanf(‘%c’',&day),case ‘0’。
case后面必须是一个整数
,或者是结果为整数的表达式
,但不能包含任何变量。
#include<stdio.h>
int main()
int a=1, b=2, re;
char c;
scanf("%c", &c);
switch(c)
case '+':
re = a + b;
break;
case '$':
re = a - b;
re++;
break;
case '#':
int other = 3; // switch语句里定义了新的变量 ,加
re = a + b + other;
break;
default:
printf("Illegal input!\\n");
break;
printf("%d\\n", re);
$gcc -o main *.c -lm
$main
Illegal input!
0
如下do-while先执行一次循环。
continue跳到循环首部,break跳出循环。
6.数组:存数据类型相同的数据,数组下标越界导致core dump段错误
定义数组时,数组的长度必须是整数
(可以是常量,也可以是变量)。
内存是线性的,b里放了2个a。
如下如果用msg[1],虽然越界了,但是系统给结构体分配很多字节,所以不报错。可用msg[0]到msg[n-1]。
函数声明和函数定义是两个概念,但变量声明和变量定义是一个概念。
7.指针:指针数组:这个数组的所有元素都是指针类型。数组指针:这个指针存放着一个数组的首地址
7.1 p是地址,*p是指向的内容:01指0x01。&a:拿a的地址赋给。地址(p),值(*p),变量名
char str[10];
char strbuf[10];
char *a(void)
FILE *fp=0;
if ((fp=fopen("ab","rt")) ==0)
printf("1111111");
if (fgets(strbuf, 10, fp) == NULL)
printf("2222222");
fclose(fp);
strcpy(str,"B");
strcat(str,strbuf);
fclose(fp);
return str;
int main()
char *b=a();
printf("%s\\n", b);
如下fclose要早于printf。
int *p 未赋值的指针称为野指针,危险的,a=100,p=&a指向合法区域。或如下空指针的两种写法也可防止野指针。
7.2 函数调用:复制a值,指向a
1.
如下main中走到increament跳到这函数中,拷贝一份给increament中的a。main中的a和increament中的a各自独立一块内存,只是名字一样。
2.
一定要通过increasement函数对a有修改怎么办?如下必须用到指针,increament运行结束后指针销毁。
7.3 函数返回:复制指针
如下当调用move_p时,p要往右移一位。move_p参数定义虽是指针,但调用时传入也是指针,复制一份。
7.4 数组和指针转换:指针转不了数组,数组可转为指针
7.5 const型指针:不可修改
8.main函数的参数:main函数的参数是从命令提示符下执行程序时传入
envp参数存放了当前程序运行环境的参数(env命令)。
9.static/extern/堆内存:realloc扩建
10.动静态库:.a,指定.so,LD_
公用函数库的public.cpp是源代码,对任何人可见,实际开发出于保密并不希望提供公用函数库源代码。C/C++提供了一个保证代码安全性方法,public.cpp编译成库(库分为静态库与动态库)
// public.h
#ifndef PUBLIC_H
#define PUBLIC_H 1
#include <stdio.h>
vo以上是关于C1数据类型,常量变量,输入输出,运算符,if/switch/循环,/数组,指针,/结构体,文件操作,/编译预处理,gdb,makefile,线程的主要内容,如果未能解决你的问题,请参考以下文章