精华内容
下载资源
问答
  • 单片机C语言实现循环移位!
    2021-01-16 13:41:47

    大家知道,大家用MCU写程序的时候,只有移位的语句,没有循环移位的语句。那么如何实现循环移位呢,详见下述:

    循环移位区别于一般移位的是移位时没有数位的丢失。循环左移时,用从左边移出的位填充字的右端,而循环右移时,用从右边移出的位填充字的左侧。这种情况在系统程序中时有使用,在一些控制程序中用得也不少。  设有数据说明:

    a=01111011,循环左移2位 正确结果: 11101101

    过程:

    b=a>>(8-2) 用来得到正常左移丢失的位和循环移位后其正确位置 b=00000001;

    a=a<<2;左移 a=11101100

    a=a|b; a=11101101

    如果不是用中间变量 a=(a>>(8-2))|(a<<2)

    总长度N(8 16 32)

    循环左移n: (a>>(N-n))|(a>>n)

    循环右移n: (a<>n)

    C语言的位运算功能是其区别于其他大多数高级程序设计语言的特色之一,用它可以方便实现一些特殊功能,灵活掌握是用C程序编写系统程序的基础。看完全文了吗?喜欢就点个 赞吧!

    更多相关内容
  • 例子1说明: header1.h 包含 header2.h; header2.h 包含 header1.h;/**circulardependency--测试循环引用*/#include#include"header1.h"intmain(void){printf("thisismyfunction!");return0;}header1.h#ifndef...

    例子1

    说明: header1.h 包含 header2.h; header2.h 包含 header1.h;/** circular dependency -- 测试循环引用 */#include #include "header1.h"int main(void) {    printf("this is my function!");    return 0;

    }

    header1.h#ifndef Header1_H_#define Header1_H_#include "header2.h"/*

    =========header2.h=======

    ========header1.h======

    #include 

    再次把 header1.h 展开

    #ifndef Header1_H_

    #define Header1_H_

    由于已经 定义过header1_H_ ;所以其中代码不会执行;

    // Other content

    #endif

    ========header1.h=====

    struct A2{

    int value;

    };

    =========header2.h=========

    *//**

    *  下面的类型如果是 指向 A2 结构体的指针; 可以不引用 header2.h 头文件; eg: struct A2 *p;

    *  也可写成 void * p ;

    *//**

    * 下面变量定义必须需要知道A2的值,所以需要引入头文件

    */struct A1 {

    int value;    struct A2 p;};#endif

    header2.h#ifndef Header2_H_#define Header2_H_#include "header1.h"struct A2{

    int value;

    };#endif

    这里通过 #ifndef X_H_ #define X_H_ #endif 来解决;

    [Headers and Includes: Why and How]http://www.cplusplus.com/foru...

    [Avoiding Circular Dependencies of header files

    ]https://stackoverflow.com/que...

    展开全文
  • C语言实现循环左移和右移

    千次阅读 2020-10-22 21:08:06
    一、win下stdlib.h中的循环移位函数 unsigned int _rotl( unsigned int value, int shift ); unsigned __int64 _rotl64( unsigned __int64 value, int shift ); unsigned int _rotr( unsigned int value, int ...

    一、win下stdlib.h中的循环移位函数

    unsigned int _rotl(
       unsigned int value,
       int shift
    );
    unsigned __int64 _rotl64(
       unsigned __int64 value,
       int shift
    );
    unsigned int _rotr(
       unsigned int value,
       int shift
    );
    unsigned __int64 _rotr64(
       unsigned __int64 value,
       int shift
    );
    

    微软帮助文档:https://www.baidu.com/link?url=vcaoeKfMNevowWj1d485LtW-iVZdaJtVdrLRyzwBP3OJFRKmIyZKMSUI19vJhHhpbq9pHmhiX42hXTu3Vc0Lc3qlWEbQSeiAimwO9Niz1Nb3Ej6ffw5HBAC443Wo3dX1pRUMxiURPHESttP7koKCaq&wd=&eqid=f5c336ef0000c801000000065f917ffd

    二、KeilC51单片机C语言库intrins.h中的循环移位函数

    unsigned char _cror_(unsigned char ,unsigned char );
    unsigned int _iror_(unsigned int ,unsigned char );
    unsigned long _lror_(unsigned long ,unsigned char );
    
    unsigned char _crol_(unsigned char ,unsigned char );
    unsigned int _irol_(unsigned int ,unsigned char );
    unsigned long _lrol_(unsigned long ,unsigned char );
    

    三、使用宏实现循环移位函数

    // value循环左移bits位
    #define rol(value, bits) ((value << bits) | (value >> (sizeof(value)*8 - bits)))
    
    // value循环右移bits位
    #define ror(value, bits) ((value >> bits) | (value << (sizeof(value)*8 - bits)))
    

    main.cpp测试代码

    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        int value = 0x01;
        int rst1 = rol(value, 1);
        int rst2 = rol(value, 31);
        int rst3 = rol(value, 33);
        printf("0x%x, 0x%x, 0x%x\n", rst1, rst2, rst3);
    
        unsigned int temp = 0x80000000;
        unsigned int rst4 = ror(temp, 1);
        unsigned int rst5 = ror(temp, 31);
        unsigned int rst6 = ror(temp, 33);
        printf("0x%x, 0x%x, 0x%x\n", rst4, rst5, rst6);
    
        return a.exec();
    }
    

    运行结果:
    在这里插入图片描述



    若对你有帮助,欢迎点赞、收藏、评论,你的支持就是我的最大动力!!!

    同时,阿超为大家准备了丰富的学习资料,欢迎关注公众号“超哥学编程”,即可领取。

    在这里插入图片描述

    展开全文
  • 它可能在识别旋转习语之前决定它需要AND指令,因为非循环移位如何对该目标起作用。 当前的x86编译器仍然使用额外的指令来屏蔽8位和16位旋转的变量计数,这可能与它们不能避免ARM上的AND相同。 这是一个错过的优化,...

    另请参阅另一个旋转问题的此答案的早期版本,其中包含有关asm gcc / clang为x86生成的更多详细信息。

    在C和C ++中表达旋转的最容易编译的方法是避免任何未定义的行为,这似乎是John Regehr的实现。 我已经调整它以按类型的宽度旋转(例如假设unsigned long正好是32位宽,尽管C / C ++只保证它至少是那么宽。我试图通过省略那种检查来保持它的可读性 事情)。

    #include // for uint32_t

    #include // for CHAR_BIT

    // #define NDEBUG

    #include

    static inline uint32_t rotl32 (uint32_t n, unsigned int c)

    {

    const unsigned int mask = (CHAR_BIT*sizeof(n) - 1); // assumes width is a power of 2.

    // assert ( (c<=mask) &&"rotate by type width or more");

    c &= mask;

    return (n<>( (-c)&mask ));

    }

    static inline uint32_t rotr32 (uint32_t n, unsigned int c)

    {

    const unsigned int mask = (CHAR_BIT*sizeof(n) - 1);

    // assert ( (c<=mask) &&"rotate by type width or more");

    c &= mask;

    return (n>>c) | (n<

    }

    适用于任何无符号整数类型,而不仅仅是unsigned long,因此您可以为其他大小制作版本。

    另请参阅具有大量安全检查的C ++ 11模板版本(包括类型宽度为2的幂的unsigned long),例如,某些24位DSP或36位大型机不是这种情况。

    我建议只使用模板作为包装器的后端,其名称包含明确的旋转宽度。 整数提升规则意味着unsigned long将执行32或64位旋转,而不是16(取决于unsigned long的宽度)。 即使uint16_t & uint16_t被C ++的整数提升规则提升为signed int,除了在int不宽于ia32intrin.h的平台上。

    在x86上,这个版本内联到单个ia32intrin.h(或ia32intrin.h),编译器可以使用它,因为编译器知道x86旋转和移位指令以与C源相同的方式屏蔽移位计数。

    编译器支持x86上的UB避免习惯用法,ia32intrin.h和__rolb用于变量计数移位:

    clang:在clang3.5之后被识别为变量计数旋转,之前是多次移位+或insn。

    gcc:自gcc4.9以来可识别的变量计数旋转,在此之前多次移位+或insn。 gcc5和更高版本也在wikipedia版本中优化了分支和掩码,仅使用ia32intrin.h或__rolb指令进行变量计数。

    icc:支持自ICC13或更早版本以来的可变计数旋转。 常量计数旋转使用ia32intrin.h,这比某些CPU(特别是AMD,但也有一些Intel)上的速度慢,占用的字节数多于__rolb,当BMI2不可用于__rorb来保存MOV时。

    MSVC:x86-64 CL19:仅识别恒定计数旋转。 (维基百科成语被识别,但分支和AND未被优化)。 在x86(包括x86-64)上使用ia32intrin.h/__rolb内部函数来自__rorb。

    ARM的gcc使用ia32intrin.h进行可变计数旋转,但仍然使用单个指令进行实际旋转:ia32intrin.h.因此gcc没有意识到旋转计数本质上是模块化的。 正如ARM文档所说,“ROR的移位长度为ia32intrin.h,超过32与ROR相同,移位长度为__rolb”。 我认为gcc在这里很困惑,因为ARM上的左/右移位使计数饱和,因此移位32或更多将清除寄存器。 (与x86不同,其中移位掩盖计数与旋转相同)。 它可能在识别旋转习语之前决定它需要AND指令,因为非循环移位如何对该目标起作用。

    当前的x86编译器仍然使用额外的指令来屏蔽8位和16位旋转的变量计数,这可能与它们不能避免ARM上的AND相同。 这是一个错过的优化,因为性能不依赖于任何x86-64 CPU上的旋转计数。 (出于性能原因,计数掩码是286引入的,因为它迭代地处理了移位,而不是像现代CPU一样处理恒定延迟。)

    顺便说一句,更喜欢旋转向右进行可变计数旋转,以避免编译器执行ia32intrin.h以在仅提供旋转右侧的ARM和MIPS等体系结构上实现左旋转。 (这可以通过编译时常量计数来优化。)

    有趣的事实:ARM实际上没有专门的移位/旋转指令,它只是MOV,源操作数在ROR模式下通过桶形移位器:ia32intrin.h.因此,旋转可以折叠到EOR指令的寄存器源操作数或一些东西。

    确保使用ia32intrin.h的无符号类型和返回值,否则它将不是旋转。 (对于x86目标,gcc会进行算术右移,移位符号位的副本而不是零,当两个移位值一起移位时会导致问题。负有符号整数的右移是C中的实现定义行为。)

    此外,确保移位计数是无符号类型,因为带有有符号类型的ia32intrin.h可能是一个补码或符号/幅度,与使用无符号或二进制补码的模块2 ^ n不同。 (参见Regehr博客文章的评论)。 __rolb在我看过的每个编译器上运行良好,每个宽度为__rorb。其他一些类型实际上打败了一些编译器的成语识别,所以不要只使用与__rolw相同的类型。

    有些编译器提供了旋转的内在函数,如果可移植版本没有在您要定位的编译器上生成良好的代码,那么它比内联asm好得多。 对于我所知道的任何编译器,没有跨平台的内在函数。 以下是一些x86选项:

    英特尔文件ia32intrin.h提供__rolb和__rorb内在函数,右移也是如此。 MSVC需要ia32intrin.h,而gcc需要__rolb. __rorb处理gcc与icc,但是clang似乎没有提供任何地方,除了在MSVC兼容模式下使用ia32intrin.h.并且它为它们发出的asm很糟糕(额外的屏蔽和 CMOV)。

    MSVC:ia32intrin.h和__rolb。

    gcc和icc(not clang):ia32intrin.h还提供__rolb/__rorb,用于向左/向右旋转8位,__rolw/__rorw(16位),__rold/__rord(32位),__rolq/__rorq(仅限64位,仅限64位) 为64位目标定义)。 对于窄旋转,实现使用__builtin_ia32_rolhi或...qi,但32位和64位旋转使用shift /或(没有针对UB的保护来定义,因为ia32intrin.h中的代码仅需要在x86上使用gcc)。 GNU C似乎没有像__builtin_popcount那样具有任何跨平台__builtin_rotate功能(它扩展到目标平台上的任何最佳功能,即使它不是单个指令)。 大多数时候,你从成语识别中获得了很好的代码。

    // For real use, probably use a rotate intrinsic for MSVC, or this idiom for other compilers. This pattern of #ifdefs may be helpful

    #if defined(__x86_64__) || defined(__i386__)

    #ifdef __MSC_VER

    #include

    #else

    #include // Not just for compilers other than icc

    #endif

    uint32_t rotl32_x86_intrinsic(rotwidth_t x, unsigned n) {

    //return __builtin_ia32_rorhi(x, 7); // 16-bit rotate, GNU C

    return _rotl(x, n); // gcc, icc, msvc. Intel-defined.

    //return __rold(x, n); // gcc, icc.

    // can't find anything for clang

    }

    #endif

    据推测,一些非x86编译器也有内在函数,但是我们不要扩展这个社区维基的答案来包含它们。 (也许在关于内在函数的现有答案中这样做)。

    (这个答案的旧版本提出了MSVC特定的内联asm(仅适用于32位x86代码),或[http://www.devx.com/tips/Tip/14043]适用于C版本。评论正在回复 那个。)

    内联asm击败了许多优化,特别是MSVC风格,因为它强制输入存储/重新加载。 精心编写的GNU C inline-asm rotate将允许计数成为编译时常量移位计数的立即操作数,但如果要移位的值也是编译时常量,它仍然无法完全优化掉 内联后。[https://gcc.gnu.org/wiki/DontUseInlineAsm。]

    展开全文
  • 原标题:单片机C语言实现NOP 循环移位首先声明:我学习 单片机C语言还不到半年,所以我还是菜鸟,我贴出的东西或许你们都知道,但我只想把我学习的经历给记录下来,希望你能找到你所想要的.我记得做学单片机做的第一个...
  • C语言位操作的算法

    2021-05-25 05:27:45
    } }/*循环移位的实现num左移N位*/ int moveToLeft(int num,intN) {for (int i = 0; i ; i++) {int t = num & (1 );//1.取出最高位的值, num = num ;//左移一位//2.先将第0位的值置给31, if (t != 0)//{ setInt...
  • C51中实现循环左移、右移的库函数:#includeunsigned char _crol_( unsigned char c, /*charactertorotateleft*/ unsigned char b); /*bitpositionstorotate*/ unsigned char _cror_(unsigned char ,unsigned char );...
  •  我记得做学单片机做的第一个实验就是做循环彩灯的实验,如果用汇编RL和RR很容易实现循环移位,但是C语言编程的移位指指令不能循环,移了后以0填充。 如果用C实现循环移位呢? 我的思路是: 比如将a=0x45循环...
  • 单片机 左右移头文件

    千次阅读 2018-07-11 09:05:13
    编程中,INTRINS.H的函数使用起来,就会让你像在用汇编时一样简便.intrins.h内部函数 描述编辑头文件INTRINS.H_crol_ 字符循环左移_cror_ 字符循环右移_irol_ 整数循环左移_iror_ 整数循环右移_...
  • i++)//开始传送8位数据,每循环一次传送一位数据 { TM1638_CLK =0; Delay1us(1); dat>>=1;//移位数据,低位在前! TM1638_DAI=CY; TM1638_CLK =1; Delay1us(1); } } void TM1638_DispData()//传送数据,并显示 { ...
  • c51循环移位的浅谈

    2021-03-07 16:48:04
    如果学习单片机,最基本的考题就是...今天就谈谈c51循环移位的见解记得如果你打开intrins.h(51自带的一个头文件),你会发现其中有关于定义_crol_()(字符循环左移函数)(一般我们用的多的是这个,呵呵),还有一个是_c...
  • 翁恺老师的c语言学习笔记

    千次阅读 2021-03-02 15:30:26
    *unsigned的初衷并非扩展数能表达的范围,而是为 了做纯二进制运算,主要是为了移位。 整数的输入输出 只有两种形式: int或long long %d: int %u: unsigned %ld: long long %lu: unsigned long long 8进制和16进制 ...
  • 原标题:结合单片机学习板学习c语言之流水灯制作 intrins.h头文件目的:实现流水灯。本文引用地址:http://www.eepw.com.cn/article/201608/294948.htm源程序:/*本程序结合STC89C51使用,晶振12M,中间用到串口中断...
  • PAGE / NUMPAGES /*szjcdz 名称数码管左移例2 编写szjcdz 日期2010.9 内容多位数码管分别显示不同数字这种扫描显示方式成为动态扫描并不停变化赋值 */ #include<reg52.h> //包含头文件一般情况不需要改动头文件包含...
  • 一:C语言实现循环移位:比如将a=0x45循环左移二位。a循环左移n位,即将原来右面(8-n)位左移n位,而将原来左端的n位移到最右面n位。实现步骤:1、将a的左端n位先放到b中的高n位中b=>>(8-n);2、将a左移n位,其...
  • 51单片机之循环移位

    万次阅读 2012-10-31 19:48:19
    51单片机之循环移位函数 今天在看书的时候看到了循环移位函数,想跟大家分享下,呵呵,大牛们不要嘲笑,由于本人刚起步,莫笑。 如果你使用keil软件编写C51程序的话,那么你可以打开Keil下的C51下的HLP文件,...
  • 51单片机基础应用设计C语言实例源码仿真300个合集: 100000秒以内的计时程序 10秒的秒表 12864LCD图形滚动演示 128X64LED 160128LCD图文演示 1602字符液晶滚动演示程序 1602液晶显示的DS1302实时时钟 16×16点阵...
  • C语言编程要点

    2017-09-18 00:10:37
    1.7 怎样才能知道循环是否提前结束了? 13 1.8 goto,longjmp()和setjmp()之间有什么区别? 13 1.9 什么是左值(lvaule)? 15 1.10 数组(array)可以是左值吗? 15 1.11 什么是右值(rvaule)? 16 1.12 运算符的优先级...
  • 本文章主要介绍利用矩阵键盘随意输入0~9数值,循环移位显示。 电路设计 这是一个相对比较简单的电路设计起来也是比较容易的,主要用到一个八位数码管和按键、单片机一个。下图所示就是博主在Proteus仿真软件中设计的...
  • C语言移位运算符

    2015-01-07 11:41:00
    移位运算符是将数据看成二进制数,对其进行向左或向右移动若干位的运算。位移位运算符分为左移和右移两种,均为双目运算符。第一运算对象是移位对象,第二个运算对象是所移的二进制位数。  位移位运算符的运算...
  • C语言:初识数组及数组的复制

    千次阅读 2022-04-10 19:16:10
    基本上C语言变量可用的类型,在数组也可使用。 数组的语法如下: 类型数组标识[长度] ,其中数组的长度或元素个数用方括号括起。如:int arr1[10],声明了10个元素的数组。 数组的初始化用花括号把数据括起来,每...
  • 8.12.2 循环中的声明 224 8.13 练习 225 第9章 函数 226 9.1 函数定义 226 9.2 函数原型 228 9.2.1 原型出现在什么时候 230 9.2.2 混合使用原型和非原型声明 230 9.2.3 合理地使用原型 231 9.2.4 原型和调用...
  • 目的:实现流水灯。...至于>>=,>>,,的移位运算符,不要天真以为它会循环移位,事实上,一个8位的字符,左移一位之后,最右边一位变成0了,而非原来最左边的一位。如果左移8位,就意味着这个8位的字符变成0x00了。
  • C语言数组元素的左移、右移

    万次阅读 2018-08-26 15:17:40
    还有一个问题就是计数问题了,这是控制循环结束的关键。 每做一次运算,这里的iCount就要加1,实在不明白的同学不嫌麻烦的话可以手写过程,当初我就是写了两遍才基本上明白了。 希望以上内容能给大家一些帮助...
  • 这些整理不避免有些错误,遗漏的地方,忘见谅====================================================atof()将字符串转换成浮点数的函数原形:double atof(const char *s)功能:把s...头文件:math。h、stdlib。hatoi...
  • 嵌入式C语言编程要点

    2021-05-23 03:39:14
    嵌入式C语言编程要点模块划分(1) 模块即是一个.c文件和一个.h文件的结合,头文件是对于模块接口的声明。(2) 某模块提供给其它模块调用的外部函数及数据需要在头文件中以extern声明。(3) 模块内的函数和全局变量需要...
  • C语言知识点汇总

    千次阅读 2022-04-06 22:20:30
    C语言——只看这一篇就够了! C语言知识点保姆级总结,这不得进你的收藏夹吃灰?! 拖了很久的C语言所学知识的简单小结,内容有点多,第一次总结也可能有错误或者不全面,欢迎随时补充说明! 数据类型 ​ 用不同...
  • C语言的内存模型基本上对应了现在vonNeumann(冯·诺伊曼)计算机的实际存储模型,很好的达到了对机器的映射,这是C/C++适合做底层开发的主要原因,另外,C语言适合做底层开发还有另外一个原因,那就是C语言对底层操作...
  • C语言基础知识总结

    2021-05-18 15:54:34
    C语言基础知识总结}#includevoid main(){int a,b;scanf("%2d%2d",&a,&b);//输入时将前两位数读入存到a中,接着两位存到b中,然后结束读取,即输入:1234,或123456结果一样printf("a=%d,b=%d\n",a,b);}#...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,255
精华内容 1,302
关键字:

c语言循环移位头文件