知识点学习总结(C语言)

一、Kafka

1.概念

  Kafka is used for building real-time data pipelines and streaming apps。
在这里插入图片描述

2.原理

  producer
  Consumergroup
  Broker
  Partition
  其他:消息状态 消息持久化 消息有效期 批量发送 push-and-pull同步异步

3.优缺点

4.应用

  日志收集: 一个公司可以用Kafka可以收集各种服务的log,通过kafka以统一接口服务的方式开放给各种consumer,例如hadoop、Hbase、Solr等。
  消息系统: 解耦和生产者和消费者、缓存消息等。

  用户活动跟踪: Kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装载到hadoop、数据仓库中做离线分析和挖掘。

  运营指标: Kafka也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。
  流式处理: 比如spark streaming和storm
  事件源

二、C语言的return

1.return的概念和作用

  return语句用来结束循环,或返回一个函数的值。
  return表示从被调函数中返回到主调函数中,返回的同时可以附带一个返回值,这个返回值可以是常量、变量,也可以是表达式。

  结束正在运行的函数,并返回函数值。

2.几种return的区别

(1)返回值int 类型的函数返回:
  Return 0:一般用在主函数结束时,按照程序开发的一般惯例,表示成功完成本函数。
  Return 1:表示返回一个代数值,一般用在子函数结尾。按照程序开发的一般惯例,表示该函数失败。

  以上两个是约定俗成,系统提供的函数绝大部分定义为int类型返回值的都是这样的。返回值是返回给系统用的,给系统看得。一般做调试的时候也会用的,当出现错误的时候可以根据返回值来确定问题出在哪一个函数上的。
  注意:返回的类型是int
(2)布尔类型返回
  Return false:返回假
  Return true:返回真
(3)其他几种

形式含义
Return;其实就是void类型函数的返回,返回后不再执行return后面的语句
Return 0;一般用在主函数结束时,表示程序正常终止,即告诉系统程序正常
Return 1;表示返回一个代数值,一般用在子函数结尾。表示程序异常终止,即告诉系统程序异常
Return -1;与“return 1;“相同

3.返回值

  计算结果表示函数执行的顺利与否(-1、0)
  返回值可以为各种数据类型,如:int,float,double,char,a,*a(指针),结构或类(c++)

4. return、break和continue异同

  相同:让后面的语句不执行
  区别:

语句区别
return结束循环、函数
break跳出循环(一层循环)
continue跳出本次循环(一层循环里的一次循环)

三、统计Linux下文件行数

1、cat example.txt | wc -l
2、wc -l example.txt
3、awk '{print NR}' test1.sh|tail -n1
4、awk 'END{print NR}' test1.sh
5、grep -n "" test1.sh|awk -F: '{print '}|tail -n1
6、sed -n '$=' test1.sh

四、C语言获取系统时间

  头文件:#include <time.h>
  代码:

time_t now ;
struct tm *tm_now ;
time(&now) ;
tm_now = localtime(&now) ;
printf("now datetime: %d-%d-%d %d:%d:%d\n", 
		tm_now->tm_year+1900, tm_now->tm_mon+1,  
		tm_now->tm_mday, tm_now->tm_hour, 
		tm_now->tm_min, tm_now->tm_sec) ;

在这里插入图片描述

五、Switch里面的局部变量声明

1、现象:

switch(num){ 
	case 1: 
		int a = 1; 
	case 2: 
		printf("hello world\n"); 
}

  编译无法通过。

2、原因解释

  上面这种情况是不会通过编译的,原因是存在变量未初始化的问题,有下面两种情况:
  
  ①num = 1:执行case 1分支,a顺利的被初始化为1,执行完case 1之后,会顺序执行case 2,此时是没有任何问题的。 因为a在整个switch块中都是可见的,而不只是自身所在的case语句内部
  
  ②num = 2:跳过case 1 分支,a在2分支内是可见的,但是不能被引用,因为此时的a是“未初始化的”,编译器为了避免这种情况,就会在编译的时候直接报错。

3、解决方法

  (1)加大括号{},构成语句块

switch(num){
case 1:
    {int a = 1;}
case 2:
    printf("hello world\n");
case 3:
    {int a=2;}     
}

  这个可以通过编译,因为此时在case ‘b ‘中a不可见(因为a在语句快中),所以不会出现上述的“不一致”现象,因此编译顺利通过。

  (2)在switch外声明变量,在case块里只做引用

int a; 
switch(num){ 
	case 1: 
		a = 1; 
	case 2: 
		printf("hello world\n"); 
}

  在整个switch块外声明变量。这样在无论开始跳转到哪个语句,都是可以直接引用a的。

六、C语言回调函数

1、概念

  回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应

  调用规范影响编译器产生的给定函数名,参数传递的顺序(从右到左或从左到右),堆栈清理责任(调用者或者被调用者)以及参数传递机制(堆栈,CPU寄存器等)。


  回调函数是指使用者自己定义一个函数,实现这个函数的程序内容,然后把这个函数(入口地址)作为参数传入别人(或系统)的函数中,由别人(或系统)的函数在运行时来调用的函数。函数是你实现的,但由别人(或系统)的函数在运行时通过参数传递的方式调用,这就是所谓的回调函数。简单来说,就是由别人的函数运行期间来回调你实现的函数。

  https://www.zhihu.com/question/19801131

  编程分为两类:系统编程(system programming)和应用编程(application programming)。
  
  所谓系统编程,简单来说,就是编写;而应用编程就是利用写好的各种库来编写具某种功用的程序,也就是应用。系统程序员会给自己写的库留下一些接口,即API(application programming interface,应用编程接口),以供应用程序员使用。所以在抽象层的图示里,库位于应用的底下。

  当程序跑起来时,一般情况下,应用程序(application program)会时常通过API调用库里所预先备好的函数。但是有些库函数(library function)却要求应用先传给它一个函数,好在合适的时候调用,以完成目标任务。这个被传入的、后又被调用的函数就称为回调函数(callback function)。

  一个形象的例子:
  你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。

  在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。回答完毕。
  https://blog.csdn.net/morixinguan/article/details/65494239

2、为什么会有回调函数

  https://blog.csdn.net/jobsss/article/details/7287140

  回调的意义在于开发者在特定条件调用用户定义的函数。
  通常,当我们想通过一个统一接口实现不同内容的时候,用回调函数来实现就非常合适。

  任何时候,如果你所编写的函数必须能够在不同的时刻执行不同的类型的工作或者执行只能由函数调用者定义的工作,你都可以用回调函数来实现。许多窗口系统就是使用回调函数连接多个动作,如拖拽鼠标和点击按钮来指定调用用户程序中的某个特定函数。

3、回调函数怎么使用

  回调在C语言中是通过函数指针来实现的,通过将回调函数的地址传给被调函数从而实现回调。因此,要实现回调,必须首先定义函数指针
在这里插入图片描述
  下面是一个具体的例子
在这里插入图片描述

4、自己如何定义和使用回调函数

  回调在C语言中是通过函数指针来实现的,通过将回调函数的地址传给被调函数从而实现回调。因此,要实现回调,必须首先定义函数指针
void Func(char *s);// 函数原型
void (*pFunc) (char *);//函数指针

   回调函数可以象普通函数一样被程序调用,但是只有它被当作参数传递给被调函数时才能称作回调函数。
在这里插入图片描述
https://blog.csdn.net/u014337397/article/details/80328277

5、回调函数适用的场合

  (1)事件驱动机制
  (2)通信协议的“推”模式
在这里插入图片描述

七、C语言数组转结构体

  今天看公司代码,遇到一个数组指针强制转换成结构体指针的地方,就在想这样做的结果会是什么,和别人讨论了一下。得到结果是,这样做是让结构体按照自己的属性重新读取数组中的数据。

八、C语言中extern的用法

https://blog.csdn.net/big_bit/article/details/51595714

1、修饰函数和变量

  在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。extern声明不是定义,即不分配存储空间。
可以多次声明,但是只能有一次定义。
  在一个文件中定义了变量和函数, 在其他文件中要使用它们, 可以有两种方式:
  (1)使用头文件,然后声明它们,然后其他文件去包含头文件;
  (2)在其他文件中直接extern

2、extern"C"作用

  比如说你用C 开发了一个DLL 库,为了能够让C ++语言也能够调用你的DLL 输出(Export) 的函数,你需要用extern “C” 来强制编译器不要修改你的函数名。
=====tu7.1
  (1)现在要写一个c语言的模块,供以后使用(以后的项目可能是c的也可能是c++的),源文件事先编译好,编译成.so或.o都无所谓。头文件中声明函数时要用条件编译包含起来,如下:—也就是把所有函数声明放在some code的位置。
=====tu7.2
  (2)如果这个模块已经存在了,可能是公司里的前辈写的,反正就是已经存在了,模块的.h文件中没有extern "C"关键字,这个模块又不希望被改动的情况下,可以这样,在你的c++文件中,包含该模块的头文件时加上extern “C”, 如下:
=====tu7.3
  (3)如果仅仅使用模块中的1个函数,而不需要include整个模块时,可以不include头文件,而单独声明该函数,像这样:
=====tu7.4
  **要注意:**当单独声明函数时候, 就不能要头文件,或者在头文件中不能写extern intThisIsTest(int a, int b);否则会有error C2732: 链接规范与“ThisIsTest”的早期规范冲突,这个错误

  还有就是要注意*.c文件中不能写成extern"C"intThisIsTest(int x,int y);在C语言的头文件中,对其外部函数只能指定为extern类型,C语言中不支持extern "C"声明,在.c文件中包含了extern "C"时会出现编译语法错误。

  (4)使用要点:
  ①可以是单一语句—头文件里

extern "C" double sqrt(double);

  ②可以是复合语句,相当于复合语句中的声明都加了extern"C"
=====tu7.5
  ③可以包含头文件,相当于头文件中的声明都加了extern"C"
=====tu7.6
  ④不可以将extern"C"添加在函数内部
  ⑤如果函数有多个声明,可以都加extern"C",也可以只出现在第一次声明中,后面的声明会接受第一个链接指示符的规则
  ⑥除extern"C",还有extern"FORTRAN"等

3、声明和定义

=====tu7.7

九、 Static

1、变量(重要♣)

(1)局部变量

  ①普通局部变量
  在任何一个函数内部定义的变量(不加static修饰符)都属于这个范畴。编译器一般不对普通局部变量进行初始化,也就是说它的值在初始时是不确定的,除非对其显式赋值。
  普通局部变量存储于进程栈空间,使用完毕会立即释放。
  ②静态局部变量
  静态局部变量使用static修饰符定义,即使在声明时未赋初值,编译器也会把它初始化为0。且静态局部变量存储于进程的全局数据区,即使函数返回,它的值也会保持不变。
  
  变量在全局数据区分配内存空间;编译器自动对其初始化,其作用域为局部作用域,当定义它的函数(??)结束时,其作用域随之结束。
  静态局部变量的效果跟全局变量有一拼,但是位于函数体内部,就极有利于程序的模块化了。–但是静态局部变量只能在其定义的该文件里有效。

(2)全局变量

  全局变量定义在函数体外部,在全局数据区分配存储空间,且编译器会自动对其初始化。
  普通全局变量对整个工程可见,其他文件可以使用extern外部声明后直接使用。也就是说其他文件不能再定义一个与其相同名字的变量了(否则编译器会认为它们是同一个变量)。

  静态全局变量仅对当前文件可见,其他文件不可访问,其他文件可以定义与其同名的变量,两者互不影响。

  在定义不需要与其他文件共享的全局变量时,加上static关键字能够有效地降低程序模块之间的耦合,避免不同文件同名变量的冲突,且不会误使用。

   变量比较分析

类别 存储空间作用局
局部变量普通局部变量堆栈区--运行时系统分配
(栈、堆)
在定义它的函数内有效,但是函数返回后失效。
静态局部变量静态存储区(数据区)--编译时编译器分配空间静态局部变量只在定义它的函数内有效,只是程序仅分配一次内存,函数返回后,该变量不会消失
全局变量普通全局变量整个工程文件内有效
静态全局变量只在定义它的文件内有效

(3)变量和内存

内存组成:
----------------------

栈stack:线性结构,先进后出FILO。存放临时创建的局部变量。
----------------------

堆heap:存放程序运行中动态分配的存储空间。
----------------------

BSS段:stack:存放程序中未初始化的或者初始化为0全局变量静态变量
--------------------------

数据段:stack:存放程序中已初始化全局变量静态变量以及字符串常量
--------------------------

代码段:stack:存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定
--------------------------

  代码段、数据段、BSS段在程序编译期间由编译器分配空间,在程序启动时加载,由于未初始化的全局变量存放在BSS段,已初始化的全局变量存放在数据段,所以程序中应该尽量少的使用全局变量以节省程序编译和启动时间;栈和堆在程序运行中由系统分配空间。

  栈stack:
  存放程序临时创建的局部变量,即函数括大括号 “{ }” 中定义的变量,其中还包括函数调用时其形参,调用后的返回值等。

  栈是由到高地址向低地址扩展的数据结构。即依次定义两个局部变量,首先定义的变量的地址是高地址,其次变量的地址是低地址。

  最后栈还具有“小内存、自动化、可能会溢出”的特点。------栈顶的地址和栈的最大容量一般是系统预先规定好的,通常不会太大。由于栈中主要存放的是局部变量,而局部变量的占用的内存空间是其所在的代码段或函数段结束时由系统回收重新利用,所以栈的空间是循环利用自动管理的,一般不需要人为操作。如果某次局部变量申请的空间超过栈的剩余空间时就有可能出现 “栈的溢出”,进而导致意想不到的后果。所以一般不宜在栈中申请过大的空间,比如长度很大的数组、递归调用重复次数很多的函数等等。

  堆heap:
  通常存放程序运行中动态分配的存储空间。堆是低地址向高地址扩展的数据结构,是一块不连续的内存区域。malloc、free 、calloc、relloc 、new等函数。

  堆具有“大内存、手工分配管理、申请大小随意、可能会泄露”的特点。堆内存是操作系统划分给堆管理器来管理的,管理器向使用者(用户进程)提供API(malloc和free等)来使用堆内存。需要程序员手动分配释放

内存地址:
十六进制表示,按字节编址,每个地址的存储单元可以存放一个字节的数据。
CPU通过内存地址获取指令和数据,并不关心这个地址所代表的空间具体在什么位置、怎么分布,因为硬件的设计保证一个地址对应着一个固定的空间,所以说:内存地址和地址指向的空间共同构成了一个内存单元。

堆内存操作函数:

void 	*malloc(size_t __size);//申请分配size个字节内存空间的地址。
void	*calloc(size_t __count, size_t __size);//申请分配count个长度为size,一共为count乘以size个字节长度的连续内存空间,并将每一个字节都初始化为0。
void	*realloc(void *__ptr, size_t __size);//ptr 表示需要修改的内存空间的地址,size 表示需要重写分配的内存空间的大小,单位是字节。
void  free(void *)

  free() 不会改变 传入的指针的值,调用 free() 后它仍然会指向相同的内存空间,但是此时该内存已无效,不能被使用。所以建议将释放完的指针设置为 NULL。例如:

    char *g = malloc(sizeof(char)); //申请sizeof(char)大小内存空间
    free(g);      //释放掉g指针指向的内存空间
    g = NULL;     //将g指针指向NULL

  free()函数只能释放动态分配的内存,并不能释放任意分配的内存,比如:

    int h[10];    //在栈上申请的10乘以sizeof(int)大小的内存空间
    free(h);      //此处报错:不能释放栈上分配的空间

*void 指针类型(void ):
  可以定义一个基类型为void的指针变量,它不指向任何类型的数据。请注意:不要把 “指向void类型” 理解为能指向 “任何的类型” 的数据,而应该理解为 “指向空类型” 或者 “不指向确定” 的类型的数据。在将它的值赋给另一个指针变量时由系统对它进行类型转换,使之适合被赋值变量的类型。

  void指针的应用场合:
  当进行纯粹的内存操作的时候,或者传递一个指向未定类型的指针时,可以使用void指针;

void* memcpy(void *addr1,void *addr2,size_t n); 

  该函数只进行纯粹的内存拷贝,包括NULL字符在内的任何内容都将被拷贝
  (1)对函数参数的限定
  (2)对函数返回的限定
  (3)void指针也常用作函数指针
tu9.1

2、函数

  函数的使用方式与全局变量类似,在函数的返回类型前加上static,就是静态函数。其特性如下:
  (1)静态函数只能在声明它的文件中可见,其他文件不能引用该函数;
  (2)不同的文件可以使用相同名字的静态函数,互不影响。

非静态函数可以在另一个文件中直接引用,甚至不必使用extern声明。

3、面向对象

4、后面补充

https://blog.csdn.net/guotianqing/article/details/79828100

十、Intptr_t

  在/usr/include/stdint.h这个头文件中找到了这个类型的定义

10.1在这里插入图片描述
  尽管在混合不同数据类型时你必须小心, 有时有很好的理由这样做. 一种情况是因为内存存取, 与内核相关时是特殊的. 概念上, 尽管地址是指针, 内存管理常常使用一个无符号的整数类型更好地完成; 内核对待物理内存如同一个大数组, 并且内存地址只是一个数组索引. 进一步地, 一个指针容易解引用; 当直接处理内存存取时, 你几乎从不想以这种方式解引用. 使用一个整数类型避免了这种解引用, 因此避免了 bug. 因此, 内核中通常的内存地址常常是 unsigned long, 利用了指针和长整型一直是相同大小的这个事实, 至少在 Linux 目前支持的所有平台上.

  因为其所值的原因, C99 标准定义了 intptr_t 和 uintptr_t 类型给一个可以持有一个指针值的整型变量. 但是, 这些类型几乎没在 2.6 内核中使用

  总而言之就是:intptr_t是为了跨平台,其长度总是所在平台的位数,所以用来存放地址。
在这里插入图片描述

十一、Printf打印指针地址

  %p–首选
  %x–也可
  %u–不推荐

十二、Linux下捕获错误:errno和strerror

1、应用场景:

  Linux系统API,如open,write,creat,close,fsync等函数返回-1,即失败,errno为错误码,对应不同的错误类型,共125个,0~124。

2、用法:

#include <stdio.h>
#include <string.h>
#include <errno.h> 
int main(void)
{
    int   fd;
    if((fd =open("/dev/dsp",O_WRONLY)) < 0)
    {
        printf("errno=%d\n,%s",errno, strerror(errno)); 
    }
    exit(0);
}

十三、Free()报错

1、现象

*** glibc detected *** ./myfirst: free(): invalid next size (fast): 0x000000000af4c0f0 ***

2、原因

  1)要free的对象被破坏了.有其它地方的越界赋值.在要free的对象前后malloc申请的内存块的使用错误的嫌疑最大.
  2)free了两次.或者malloc其实没有成功,就free了.
  3)指向free对象(内存)的指针不正确.(不是malloc时获得的指针)

十四、strcpy和memcpy的区别

  strcpy和memcpy都是标准C库函数,它们有下面的特点。

1、Strcpy

  strcpy提供了字符串的复制。即strcpy只用于字符串复制,并且它不仅复制字符串内容之外,还会复制字符串的结束符。
  已知strcpy函数的原型是:

char* strcpy(char* dest, const char* src);

2、Memcpy

  memcpy提供了一般内存的复制。即memcpy对于需要复制的内容没有限制,因此用途更广。
  原型:

void *memcpy( void *dest, const void *src, size_t count );

3、区别

  strcpy和memcpy主要有以下3方面的区别。
  (1)、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
  (2)、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
  (3)、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy。

十五、Malloc(0)问题

1、malloc函数

#include <stdlib.h>

在这里插入图片描述
  * 或者是 [] 都是访问对象,就是 malloc(0)的返回值 不管是什么 都不能做*操作 或者是 []操作。*p->m其实是(p).m

总结:
  对于这里 malloc(0)返回值,不是编译没错运行每次 你就可以使用,不是malloc 有分配你就可以使用,因为根据标准的描述 你看到的情况仅仅是千千万万种可能性当中,微不足道的一种而已,没代表性 没价值的。

  记住一件事就行了:别对malloc(0)的返回值做 除了free以外的任何操作

  至于面试题,渣渣面试题 如果你想要那份工作 你就写面试官想看到的答案 就这么简单。

十六、C语言rename函数:重命名文件或目录

1、语法

#include <stdio.h>
int  rename(char * oldname, char * newname);

2、用途

  函数rename()用于重命名文件、改变文件路径或更改目录名称。
  重命名文件:

  如果newname指定的文件存在,则会被删除。
  如果newname与oldname不在一个目录下,则相当于移动文件。
  重命名目录:

  如果oldname和oldname都为目录,则重命名目录。
  如果newname指定的目录存在且为空目录,则先将newname删除。
  对于newname和oldname两个目录,调用进程必须有写权限。
  重命名目录时,newname不能包含oldname作为其路径前缀。例如,不能将/usr更名为/usr/foo/testdir,因为老名字( /usr/foo)是新名字的路径前缀,因而不能将其删除。

十七、C变量默认值

  如果是全局变量,所有的全局变量都赋零,字符变量都赋NULL即0.指针变量也是NULL。即全部变量都自动初始化了。
  如果是局部变量,所有的变量都不初始化,因此为随机数。如果不赋值就使用,很危险。需要先初始化再使用。

十八、数据结构–队列

  特性:先进先出,来源于生活中的排队服务。
在这里插入图片描述
  队列几个操作:
在这里插入图片描述
  队列可以由数组和链表两种形式实现队列操作(c语言)。
  分类:
    顺序队列:每次插入,指针rear加一,每次删除,指针front加一。
    循环队列:
    https://blog.csdn.net/lpp0900320123/article/details/20694409

十九、kylin操作系统遇到问题

(1)“权限为777的.sh脚本无法执行问题”

  脚本test.sh内容:

#!/bin/bash
echo ‘haha’

  设置权限为777了,执行时候,系统还是提示权限不够。
在这里插入图片描述
在这里插入图片描述
  排查原因:在网上找了很多资料,大致说的原因有1)格式不对,需要转成UNIX的;2)权限不够。尝试了,还是没法解决
  最终是一位大牛解决的,说是麒麟系统(银河)有一个安全管控开关,需要进入ui界面里,关掉。具体怎么尝试的我也不清楚,尝试了还是失败。
  总结:使用kylin-ui命令,进入ui设置里安全管控开关关掉即可。

(2)“编译选项问题,-fPIC”

  -fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

/usr/lib64/gcc/x86_64-suse-linux/4.3/../../../../x86_64-suse-linux/bin/ld: ../../CI/script/server/lib/libz.a(adler32.o): relocation R_X86_64_32 against `.text' can not be used when making a shared object; recompile with -fPIC
../../CI/script/server/lib/libz.a: could not read symbols: Bad value

  原因:提示说需要-fPIC编译,然后在链接动态库的地方加上-fPIC的参数编译结果还是报错,需要把共享库所用到的所有静态库都采用-fPIC编译一遍,才可以成功的在64位环境下编译出动态库。

(3)“链接库的先后顺序”

  makefile中链接多个库的时候,这好几个库的先后顺序也可能导致最终编译成功与否的原因。

二十、MFC报错,右键兼容性设置问题

  vs2017编译MFC程序报错
  “无法打开源文件“stdafx.cpp":no such file or driectory”
  解决:
  右键,选中“属性”,将“以兼容模式运行这个程序”前面的勾取消掉。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值