鱼C论坛

 找回密码
 立即注册
查看: 1987|回复: 3

[技术交流] 000-小知识->点滴积累

[复制链接]
发表于 2018-7-25 23:02:20 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 moc 于 2018-10-29 18:57 编辑

1、预编译
        #pragma once 和  #ifndef... #define... #endif
  示例:
        //方式一
       #pragmaonce
       ... ... // 声明、定义语句
        //方式二
         #ifndef  __SOMEFILE_H__
        #define   __SOMEFILE_H__
        ... ... // 声明、定义语句
        #endif

   #ifndef的方式受C/C++语言标准支持。它不仅可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件(或者代码片段)不会被不小心同时包含。
   当然,缺点就是如果不同头文件中的宏名不小心“撞车”,可能就会导致你看到头文件明明存在,但编译器却硬说找不到声明的状况——这种情况有时非常让人郁闷。
   #pragma once 一般由编译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正。
  方式二由语言支持所以移植性好,方式一可以避免名字冲突。

2、运算符~和!
        !:称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。例:!(A && B)。
        ~:一元运算符,按位取反,具有"翻转"位效果,即0变成1,1变成0。
注意:即使bool flage = 1; 在flage = ~flage后,flage认为1。因为bool在内存中也占一个字节。

3、宏
1、宏定义
        1. 简单的宏定义:
                #define <宏名>  <字符串>
                例: #define PI 3.1415926
        2 .带参数的宏定义
                #define <宏名> (<参数表>) <宏体>
                例: #define A(x) x
          一个标识符被宏定义后,该标识符便是一个宏名。这时,在程序中出现的是宏名,在该程序被编译前,先将宏名用被定义的字符串替换,这称为宏替换,替换后才进行编译,宏替换是简单的替换。
2、宏替换发生的时机
         为了能够真正理解#define的作用,让我们来了解一下对C语言源程序的处理过程。当我们在一个集成的开发环境中将编写好的源程序进行编译时,实际经过了预处理、编译、汇编和连接几个过程。其中预处理器产生编译器的输入,它实现以下的功能:
        (1)文件包含
                    可以把源程序中的#include 扩展为文件正文,即把包含的.h文件找到并展开到#include 所在处。
        (2)条件编译
                    预处理器根据#if和#ifdef等编译命令及其后的条件,将源程序中的某部分包含进来或排除在外,通常把排除在外的语句转换成空行。
        (3)宏展开
                    预处理器将源程序文件中出现的对宏的引用展开成相应的宏定义,即本文所说的#define的功能,由预处理器来完成。
            经过预处理器处理的源程序与之前的源程序有所有不同,在这个阶段所进行的工作只是纯粹的替换与展开,没有任何计算功能,所以在学习#define命令时只要能真正理解这一点,这样才不会对此命令引起误解并误用。
3、常见问题
例1:
  1. #define N 2+2
  2. void main()
  3. {
  4.    int a=N*N;
  5.    printf(“%d”,a);
  6. }
复制代码

        宏展开是在预处理阶段完成的,这个阶段把替换文本只是看作一个字符串,并不会有任何的计算发生,在展开时是在宏N出现的地方 只是简单地使用串2+2来代替N,并不会增添任何的符号,所以对该程序展开后的结果是a=2+2*2+2,计算后=8,这就是宏替换的实质。
例2:
  1. #define area(x) x*x
  2. void main()
  3. {
  4.     int y = area(2+2);  
  5.     printf(“%d”,y);
  6. }
复制代码

        在这个程序里,2+2即为area宏中的参数,应该由它来替换宏定义中的x,即替换成2+2*2+2=8了。#define   area(x) ((x)*(x)),不要觉得这没必要,没有它,是不行的。要想能够真正使用好宏定义,那么在读别人的程序时,一定要记住先将程序中对宏的使用全部替换成它所代表的字符串,不要自作主张地添加任何其他符号,完全展开后再进行相应的计算,就不会写错运行结果。 如果是自己编程使用宏替换,则在使用简单宏定义时,当字符串中不只一个符号时,加上括号表现出优先级,如果是带参数的宏定义,则要给宏体中的每个参数加上括号,并在整个宏体上再加一个括号。
4、宏中的特殊符号 #、##、 #@
1.  #define Conn(x,y) x##y
x##y表示x连接y,举例说:
        int n = Conn(123,456);      // 结果就是n=123456;
        char* str = Conn("abc", "123");    // 结果就是 str = "abc123";
2. #define ToChar(x) #@x
#@x,就是给x加上单引号,结果返回是一个const char。
        char a = ToChar(1);     //结果就是a='1';
3. #define ToString(x) #x
#x是给x加双引号
        char* str = ToString(123132);     //str="123132";
4、全局变量的管理 与 extern
项目中不同cpp文件中的全局变量,都是在全局作用于下,如果相互include,会产生重定义。
可以将全局变量统一管理,项目中用extern.cpp与extern.h统一管理。
extern.cpp
  1. // 把所有全局变量的定义都放在该文件夹下。统一管理
  2. int g_a = 10;
  3. int g_b = 20;
  4. int g_c = 30;
复制代码

extern.h
  1. // 把所有全局变量用extern扩展,然后在要用到这些变量的文件中只需#include “extern.h” 即可。
  2. #pragma once
  3. extern int g_a;
  4. extern int g_b;
  5. extern int g_c;
复制代码

5、Visual studio 自定义补全代码
1.找到补全代码的文件所在的位置   工具--> 代码片段管理器  -->  语言(visual C++)
79.jpg
2.定位到该路径,复制一份if.snippet文件到桌面,双击打开(打开后拖动文件到所打开的窗口)
12.jpg
3.在xml格式的文件中修改Title,Shortcut,CDATA标签中的内容,修改后保存,并重命名文件,如#1.snippet.
4.把修改名称的文件放入1中找到的位置。这样在Visual studio编译器中就可以使用#1来补全代码。
6、C++11新特性  auto遍历
        像python中的for ... in ...,遍历容器一样,C++11的新特性中也有了该功能:for (auto each : 容器) {...;}
1. 遍历字符串:
  1. std::string str = “hello, world”;  
  2. for(auto ch : str) {  
  3.      std::cout << ch << std::endl;  
  4. }
复制代码

2. 遍历数组
  1. int arr[] = {1, 2, 3, 4};  
  2. for(auto i : arr) {  
  3.      std::cout<< i << std::endl;  
  4. }
复制代码

3.遍历stl 容器
  1. std::vector<std::string> str_vec = {“i”, “like”,  "google”};  
  2. for(auto& it : str_vec) {  
  3.      it = “c++”;  
  4. }
复制代码

4. 遍历stl map   (遍历map返回的是pair变量,不是迭代器。)
  1. std::map<int, std::string> hash_map = {{1, “c++”}, {2, “java”}, {3, “python”}};  
  2. for(auto it : hash_map) {  
  3.      std::cout << it.first << “\t” << it.second << std::endl;  
  4. }  
复制代码

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-9-9 22:27:33 | 显示全部楼层
有时候发现楼主记的笔记好细,看的不太懂。是不是会用就好了呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-9-9 22:35:53 | 显示全部楼层
Kitty喜欢小鱼干 发表于 2018-9-9 22:27
有时候发现楼主记的笔记好细,看的不太懂。是不是会用就好了呢?

会用就行啦,理解了更容易记住,我记下来也是为了忘了就来看看。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-9-10 10:56:43 | 显示全部楼层
moc 发表于 2018-9-9 22:35
会用就行啦,理解了更容易记住,我记下来也是为了忘了就来看看。

这个学科,不在网上做一些笔记的话,确实很容易忘掉。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-26 20:25

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表