当前位置:  编程技术>c/c++/嵌入式
本页文章导读:
    ▪USACO 2.4.1 The Tamworth Two      牛和农夫按照固定的走法在10x10的地图中走,每分钟走一步,求经过几分钟相遇。永远不能相遇输出0.纯模拟的题。判断永远不能相遇的方法是如果遇到了一个先前的状态,那么肯定存在循环.........
    ▪uint8_t / uint16_t / uint32_t /uint64_t 的简单介绍      在nesc的代码中,你会看到很多你不认识的数据类型,比如uint8_t等。咋一看,好像是个新的数据类型,不过C语言(nesc是C的扩展)里面好像没有这种数据类型啊!怎么又是u又是_t的?很多人有.........
    ▪size_t      size_t(2012-10-10 19:12:39)转载▼标签:杂谈       今天我来讲讲size_t,借此来说明我的一些代码风格。   我们都知道size_t这个是为移植性服务的,32位系统是32位无符号整.........

[1]USACO 2.4.1 The Tamworth Two
    来源:    发布时间: 2013-10-17

牛和农夫按照固定的走法在10x10的地图中走,每分钟走一步,求经过几分钟相遇。永远不能相遇输出0.

纯模拟的题。

判断永远不能相遇的方法是如果遇到了一个先前的状态,那么肯定存在循环,必定不能相遇。

程序中把状态表示为牛和农夫的位置以及面向的方向,通过map判断是否遇到重复状态,因为map中不存在的键会有默认值,对于bool来说就是false。

一点点空间的优化是地图只用存一份,牛和农夫不显示在地图上,尽通过状态里的点间接表示。

1 /*
2 ID: xjtuacm1
3 PROG: ttwo
4 LANG: C++
5 */
6 #include<iostream>
7 #include<stack>
8 #include<cstring>
9 #include<cstdio>
10 #include<queue>
11 #include<algorithm>
12 #include<map>
13 using namespace std;
14
15 const int N = 10;
16 enum direction {NORTH, EAST, SOUTH, WEST};
17
18 struct point
19 {
20 int x, y;
21 point(int xx= 0, int yy = 0) :x(xx), y(yy) {}
22 void set(int xx, int yy)
23 {
24 x = xx;
25 y = yy;
26 }
27 bool operator==(const point& pt) const
28 {
29 return x == pt.x && y == pt.y;
30 }
31 };
32
33 struct state
34 {
35 int d[2];
36 point pt[2];
37 state() { d[0] = d[1] = NORTH; }
38
39 bool operator<(const state& s) const
40 {
41 return memcmp(this, &s, sizeof(state)) < 0;
42 }
43 };
44
45 map<state, bool> h;
46 char pane[N][N];
47
48 inline bool inRange(point pt)
49 {
50 return pt.x >= 0
51 && pt.x < 10
52 && pt.y >= 0
53 && pt.y < 10;
54 }
55
56 bool met(const state& s)
57 {
58 return s.pt[0] == s.pt[1];
59 }
60
61 void next(state& s)
62 {
63 point npt[2];
64
65 for(int i = 0; i!= 2; i++)
66 {
67 switch(s.d[i])
68 {
69 case NORTH:
70 npt[i].set(s.pt[i].x - 1, s.pt[i].y);
71 break;
72 case EAST:
73 npt[i].set(s.pt[i].x, s.pt[i].y + 1);
74 break;
75 case SOUTH:
76
    
[2]uint8_t / uint16_t / uint32_t /uint64_t 的简单介绍
    来源:    发布时间: 2013-10-17

在nesc的代码中,你会看到很多你不认识的数据类型,比如uint8_t等。咋一看,好像是个新的数据类型,不过C语言(nesc是C的扩展)里面好像没有这种数据类型啊!怎么又是u又是_t的?很多人有这样的疑问。论坛上就有人问:以*_t结尾的类型是不是都是long型的?在baidu上查一下,才找到答案,这时才发觉原来自己对C掌握的太少。

那么_t的意思到底表示什么?具体的官方答案没有找到,不过我觉得有个答案比较接近。它就是一个结构的标注,可以理解为type/typedef的缩写,表示它是通过typedef定义的,而不是其它数据类型。

uint8_t,uint16_t,uint32_t等都不是什么新的数据类型,它们只是使用typedef给类型起的别名,新瓶装老酒的把戏。不过,不要小看了typedef,它对于你代码的维护会有很好的作用。比如C中没有bool,于是在一个软件中,一些程序员使用int,一些程序员使用short,会比较混乱,最好就是用一个typedef来定义,如: typedef char bool;

一般来说,一个C的工程中一定要做一些这方面的工作,因为你会涉及到跨平台,不同的平台会有不同的字长,所以利用预编译和typedef可以让你最有效的维护你的代码。为了用户的方便,C99标准的C语言硬件为我们定义了这些类型,我们放心使用就可以了。

按照posix标准,一般整形对应的*_t类型为: 1字节     uint8_t 2字节     uint16_t 4字节     uint32_t 8字节     uint64_t

附:C99标准中inttypes.h的内容 00001 /* 00002    inttypes.h 00003 00004    Contributors: 00005      Createdby Marek Michalkiewicz <marekm@linux.org.pl> 00006 00007    THISSOFTWARE IS NOT COPYRIGHTED 00008 00009    Thissource code is offered for use in the public domain.  You may 00010    use,modify or distribute it freely. 00011 00012    Thiscode is distributed in the hope that it will be useful, but 00013    WITHOUTANY WARRANTY.  ALLWARRANTIES, EXPRESS OR IMPLIED ARE HEREBY 00014    DISCLAIMED.  This includes but is not limited towarranties of 00015    MERCHANTABILITYor FITNESS FOR A PARTICULAR PURPOSE. 00016  */ 00017 00018 #ifndef __INTTYPES_H_ 00019 #define __INTTYPES_H_ 00020 00021 /* Use [u]intN_t if you need exactly N bits. 00022    XXX- doesn't handle the -mint8 option.  */ 00023 00024 typedefsigned char int8_t; 00025 typedefunsigned char uint8_t; 00026 00027 typedefint int16_t; 00028 typedefunsigned int uint16_t; 00029 00030 typedeflong int32_t; 00031 typedefunsigned long uint32_t; 00032 00033 typedeflong long int64_t; 00034 typedefunsigned long long uint64_t; 00035 00036 typedefint16_t intptr_t; 00037 typedefuint16_t uintptr_t; 00038 00039 #endif

------------

http://blog.sina.com.cn/s/blog_6aea878e0100tl0f.html

1>. 在写程序时注意"无符号类型"的使用, 各种类型边界值的情况.

如:
a>
当某个数据不可能为负数时我们一定要考虑用以下类型:
unsigned char,
unsigned int, uint32_t, size_t, uint64_t, unsigned long
int,
b> 当有些数据你不知道是正负时一定不要用"a>"中的类型,
不然他永远也不可能为负.


c> 数据的边界值要多注意, 如:

uint32_t a, b, c;

uint64_t
m;


m = a * b + c;
在该运算中可能出现错误,
"a*b"的类型可能超过uint32_t的最大值,这时一定不要忘了类型转换.
m
= ((uint64_t)a) * b + c;

2>. 在适当的时候要会自我定义数据类型.

我们都知道linux C开发中的常见扩展数据类型的定义有:uint8_t, uint16_t, uint32_t, uint64_t, size_t,
ssize_t, off_t .... 他之所以要自己定义出数据类型是有道理的, 如: typdef unsigned int uint32_t;
表示uint32_t为32位无符号类型数据, 其实size_t也是32位无符号数据类型, 为什么不直接写"unsigned int"呢?

为了程序的可扩展性, 假如将来我们需要的数据大小变成了64bit时,我们只需要将typedef long long size_t就可以了,
不然我们可要修改好多好多的地方了.
这种设计我们同样可以应用到自己的开发中来,当自己设计一个int类型保存某种数据时,但你又没把握将来是不是要用long
int时你可以引用一个自己定义的数据类型的啊!


stdint.h
-----------------------------
typedef
unsigned int
uint32_t;


uint32_t.c
-----------------------------
#include
<stdio.h>
#if 0
#include
<stdint.h> //
uint32_t
#endif

typedef
unsigned int uint32_t;
typedef
unsigned long long
uint64_t;

int
main()
{
uint32_t
a;
a =
12;
printf("a = %x\n",
a);
printf("sizeof(a) = %d\n",
sizeof(a));

uint64_t
b;
b =
12;
printf("b = %x\n",
b);
printf("sizeof(b) = %d\n",
sizeof(b));
}



a = c
sizeof(a) = 4
b =
c
sizeof(b) = 8

 

本文链接


    
[3]size_t
    来源:    发布时间: 2013-10-17

size_t
(2012-10-10 19:12:39)
转载▼
标签:
杂谈
   
   今天我来讲讲size_t,借此来说明我的一些代码风格。
   我们都知道size_t这个是为移植性服务的,32位系统是32位无符号整形,64位系统是64位无符号整形。比如我举个例子
   A:
   size_t add_32_t(unsigned int op1, unsigned int op2)
   {
            return op1 + op2;
   }
   B:
   uint64_t add_32_t(uint32_t op1, uint32_t op2)
   {
            return op1 + op2;
   }
   再比如一个数据结构
   A:
   struct XXX  //这个XXX可以看作是一个可变长度的块的块头
   {
        char name[NAME_SIZE];
        size_t record_cnt   //record_cnt记录了record数组的大小
        YYY record[0]
   }
   B:
   struct XXX  //这个XXX可以看作是一个可变长度的块的块头
   {
        char name[NAME_SIZE];
        uint32_t record_cnt   //record_cnt记录了record数组的大小
        YYY record[0]
   }
    哪一种代码好呢?我喜欢带数字的整形类型的(stdint.h)中定义的,因为这个不用思考,我在编码的时候看到的是uint32_t,那么写这个代码的当事人就考虑了全部可能的溢出,size等问题。如果是size_t,那么这个头部的大小是不确定的(在不同系统中),而且溢出的情况也是不确定的。
  
    大家可以用facebook开源的folly代码,grep size_t *.h *.cpp 在grep一下 uint32_t 和 uint64_t就能体会出区别。

    有的人一天写30行代码,有的人一天写300行代码,如果你写得多,一定用一些简单,可靠的方法来保证尽可能的少犯错误,不要为什麽移植性来考虑,这个都是库函数程序员考虑的问题,我编码这么多年,要说遇到代码有移植性的这个需求的,也非常罕见,有几个人会把32位下的代码移植到64位上来,或者64位的移植到32位上,起码,我绝少遇到。
    最后在举个例子
    比如我在64位程序下写了这么个函数
    bool XXX(uint32_t xxx,uint32_t yyy){}
    那么这个函数移植到32位系统,其工作的结果也是你可以预期的,和64位一样
    但如果
    bool XXX(size_t xxx, size_t yyy){}
    这个函数移植到32位系统,运行结果也是可以预期的嘛?
    所以,同志们,我建议用确定的东西,不要用不确定的东西。不过你们也要独立思考,不要被我忽悠,我只是分享我的一些经验,也许是错误的,不合适的,但这个确实是合适我的,起码我放心。

本文链接


    
最新技术文章:
 




特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3