Question: 怎么知道BYTE* 指针指向内存的大小？

为什么不自己记录呢？

引用 46 楼 my_live_123 的回复:顺便贴上malloc.c的源码地址 http://code.woboq.org/userspace/glibc/malloc/malloc.c.html  非常感谢您的指导，我再琢磨琢磨，我觉的这个帖子斑竹应该加精啊

引用 37 楼 xmxqiyan 的回复:上面说的8个字节可能还小了，我这里试了16个字节应该包含了申请的大小 平台不一样申请占用的大小不一样。  printf("输入数据大小："); 		scanf("%d", &size); 		ptr = new unsigned char[size]; 		p = ptr; 		for(i = 0; i <= 16; i++) 		{ 			printf("Address %p value:0x%X(%d)\r\n", p, *p, *p); 			p --; 		} 		delete(ptr);    要是前16个字节有后面申请空间信息的话，那指针是怎么判断真正数据从哪里开始的呢？》

引用 38 楼 xmxqiyan 的回复:自己可以写一个结构体来表示前面16字节的内容   typedef struct  { 	unsigned int size;		// 申请到的内存大小 	unsigned int flag;		// 若为1表示申请状态 	unsigned int totoal;	// 当前申请的总数，不一定是用户申请的，可能还包含系统申请的部分 	unsigned int reserved;	// 未知 }_mem_control_block;   测试代码更新如下：  unsigned char *ptr; 	unsigned char *p; 	int size; 	int i; 	_mem_control_block  *memctrl;  	while(1) 	{ 		printf("输入数据大小："); 		scanf("%d", &size); 		ptr = new unsigned char[size]; 		p = ptr;  		/*for(i = 0; i <= 16; i++) 		{ 			printf("Address %p value:0x%X(%d)\r\n", p, *p, *p); 			p --; 		} 		delete(ptr); 		*/  		//delete(ptr); 测试 		memctrl = (_mem_control_block *)(p - sizeof(_mem_control_block)); 		printf("申请地址：%p\r\n", p); 		printf("申请大小：%d\r\n", memctrl->size); 		printf("申请状态：%s\r\n", memctrl->flag == 1? "有效":"无效"); 		printf("当前总数量：%d\r\n",memctrl->totoal); 		printf("\r\n"); 	}     非常感谢您的回复，不知道memctrl这个函数来自何处，上面直接用打印前几个字节的解析方法跟这个有什么不同？

alloc_perturb此函数就是初始分配的内存，即全部清零！  然后看逆过程free  void 2914__libc_free (void *mem) 2915{ 2916  mstate ar_ptr; 2917  mchunkptr p;                          /* chunk corresponding to mem */ 2918 2919  void (*hook) (void *, const void *) 2920    = atomic_forced_read (__free_hook); 2921  if (__builtin_expect (hook != NULL, 0)) 2922    { 2923      (*hook)(mem, RETURN_ADDRESS (0)); 2924      return; 2925    } 2926 2927  if (mem == 0)                              /* free(0) has no effect */ 2928    return; 2929 2930  p = mem2chunk (mem); 2931 2932  if (chunk_is_mmapped (p))                       /* release mmapped memory. */ 2933    { 2934      /* see if the dynamic brk/mmap threshold needs adjusting */ 2935      if (!mp_.no_dyn_threshold 2936          && p->size > mp_.mmap_threshold 2937          && p->size <= DEFAULT_MMAP_THRESHOLD_MAX) 2938        { 2939          mp_.mmap_threshold = chunksize (p); 2940          mp_.trim_threshold = 2 * mp_.mmap_threshold; 2941          LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2, 2942                      mp_.mmap_threshold, mp_.trim_threshold); 2943        } 2944      munmap_chunk (p); 2945      return; 2946    } 2947 2948  ar_ptr = arena_for_chunk (p); 2949  _int_free (ar_ptr, p, 0); 2950}  重点： 0.分配的hook，参考gnu相关内容，不管它 1.传入空指针，直接返回，没啥作用 2.p = mem2chunk (mem); 这是个宏  #define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))  看看多熟悉，上面是+，这里是减 3.如果是映射方式分配的大内存，用解映射方式释放，不管它 4.最后两句 倒数第二句全是宏，展开如下  ar_ptr = (((p)-> size & 0x4) ?               ((heap_info *) ((unsigned long) (p) & ~((10 * 10) - 1)))->ar_ptr : &main_arena);  具体没有深究，暂且不论了 最后一句，它要完成释放的工作 这也是一个很大的函数，看主要部分 进此函数有一句 size = chunksize (p); 这个是个下面这个宏  #define PREV_INUSE 0x1 #define IS_MMAPPED 0x2 #define NON_MAIN_ARENA 0x4 #define SIZE_BITS (PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) #define chunksize(p)         ((p)->size & ~(SIZE_BITS))  意思就是屏蔽掉低3位，就得到chunk的大小了, 骚年，秒懂没？这就是你要的大小，至于windows下其怎么malloc和free的，自己研究吧  下面是测试程序  #include <stdio.h>  #include <stdlib.h>  #include <malloc.h>   struct malloc_chunk { 	size_t prev_size; 	size_t size; 	struct malloc_chunk *fd; 	struct malloc_chunk *bk; 	struct malloc_chunk *fd_nextsize; 	struct malloc_chunk *bk_nextsize; };  typedef struct malloc_chunk *mchunkptr;  int main(int argc, char *argv[]) { 	void *mem; 	mchunkptr p; 	int ret; 	int i;  	for(i = 0; i < 10; ++i) { 		mem = malloc(ret = rand() % 1024);  		p = ((mchunkptr) ((char *) (mem) - 2 * (sizeof(size_t)))); 		printf("malloc size : %d; chunk size : %d\n", ret, p->size & ~0x7);  		free(mem); 	} 	exit(0); 	 }  运行结果

大家都只讨论在理论上，没有人深入实践中研究到底怎么回事 咱一起看看GNU的glib的malloc和free 开篇强调，此算法不一定是最好的，但是是普遍适用的  44* Why use this malloc? 45 46  This is not the fastest, most space-conserving, most portable, or 47  most tunable malloc ever written. However it is among the fastest 48  while also being among the most space-conserving, portable and tunable. 49  Consistent balance across these factors results in a good general-purpose 50  allocator for malloc-intensive programs. 51 52  The main properties of the algorithms are: 53  * For large (>= 512 bytes) requests, it is a pure best-fit allocator, 54    with ties normally decided via FIFO (i.e. least recently used). 55  * For small (<= 64 bytes by default) requests, it is a caching 56    allocator, that maintains pools of quickly recycled chunks. 57  * In between, and for combinations of large and small requests, it does 58    the best it can trying to meet both goals at once. 59  * For very large requests (>= 128KB by default), it relies on system 60    memory mapping facilities, if supported.  如果是你的性能瓶颈，可以自己实现malloc和free，据说有公司这样做  malloc函数实现  2878void * 2879__libc_malloc (size_t bytes) 2880{ 2881  mstate ar_ptr; 2882  void *victim; 2883 2884  void *(*hook) (size_t, const void *) 2885    = atomic_forced_read (__malloc_hook); 2886  if (__builtin_expect (hook != NULL, 0)) 2887    return (*hook)(bytes, RETURN_ADDRESS (0)); 2888 2889  arena_get (ar_ptr, bytes); 2890 2891  if (!ar_ptr) 2892    return 0; 2893 2894  victim = _int_malloc (ar_ptr, bytes); 2895  if (!victim) 2896    { 2897      LIBC_PROBE (memory_malloc_retry, 1, bytes); 2898      ar_ptr = arena_get_retry (ar_ptr, bytes); 2899      if (__builtin_expect (ar_ptr != NULL, 1)) 2900        { 2901          victim = _int_malloc (ar_ptr, bytes); 2902          (void) mutex_unlock (&ar_ptr->mutex); 2903        } 2904    } 2905  else 2906    (void) mutex_unlock (&ar_ptr->mutex); 2907  assert (!victim || chunk_is_mmapped (mem2chunk (victim)) || 2908          ar_ptr == arena_for_chunk (mem2chunk (victim))); 2909  return victim; 2910} 2911libc_hidden_def (__libc_malloc)  重点是这句  victim = _int_malloc (ar_ptr, bytes); 这函数非常大，过百行，有兴趣的骚年，自己读去哈 主题思想就是根据用户申请的大小，做出不同的分配方案 怎么分配先不管喽，主要解决楼主的问题 其中有三句共有的重要的代码    void *p = chunk2mem (victim);   alloc_perturb (p, bytes); return p;  victim是分配算法分配的内存地址,chunk2mem是个宏  #define chunk2mem(p)   ((void*)((char*)(p) + 2*SIZE_SZ))  其中SIZE_SZ也是个宏，展开就是sizeof(size_t), 为什么加两个无符号整型大小呢？ 看这里  struct malloc_chunk { 1112 1113  INTERNAL_SIZE_T      prev_size;  /* Size of previous chunk (if free).  */ 1114  INTERNAL_SIZE_T      size;       /* Size in bytes, including overhead. */ 1115 1116  struct malloc_chunk* fd;         /* double links -- used only if free. */ 1117  struct malloc_chunk* bk; 1118 1119  /* Only used for large blocks: pointer to next larger size.  */ 1120  struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */ 1121  struct malloc_chunk* bk_nextsize; 1122};  这个数据结构就malloc块信息结点，其中 INTERNAL_SIZE_T就是size_t,上文加上那个两个size_t就是跳过前两个成员 int_malloc返回偏移后的p，回到_lib_malloc中，return victim；即就是偏移后的p，即用户malloc得到的地址  布局的介绍：  /* 1126   malloc_chunk details: 1127 1128    (The following includes lightly edited explanations by Colin Plumb.) 1129 1130    Chunks of memory are maintained using a `boundary tag' method as 1131    described in e.g., Knuth or Standish.  (See the paper by Paul 1132    Wilson ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a 1133    survey of such techniques.)  Sizes of free chunks are stored both 1134    in the front of each chunk and at the end.  This makes 1135    consolidating fragmented chunks into bigger chunks very fast.  The 1136    size fields also hold bits representing whether chunks are free or 1137    in use. 1138 1139    An allocated chunk looks like this: 1140 1141 1142    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1143	    |             Size of previous chunk, if allocated            | | 1144	    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1145	    |             Size of chunk, in bytes                       |M|P| 1146      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1147	    |             User data starts here...                          . 1148	    .                                                               . 1149	    .             (malloc_usable_size() bytes)                      . 1150	    .                                                               | 1151nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1152	    |             Size of chunk                                     | 1153	    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1154 1155 1156    Where "chunk" is the front of the chunk for the purpose of most of 1157    the malloc code, but "mem" is the pointer that is returned to the 1158    user.  "Nextchunk" is the beginning of the next contiguous chunk. 1159 1160    Chunks always begin on even word boundaries, so the mem portion 1161    (which is returned to the user) is also on an even word boundary, and 1162    thus at least double-word aligned. 1163 1164    Free chunks are stored in circular doubly-linked lists, and look like this: 1165 1166    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1167	    |             Size of previous chunk                            | 1168	    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1169    `head:' |             Size of chunk, in bytes                         |P| 1170      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1171	    |             Forward pointer to next chunk in list             | 1172	    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1173	    |             Back pointer to previous chunk in list            | 1174	    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1175	    |             Unused space (may be 0 bytes long)                . 1176	    .                                                               . 1177	    .                                                               | 1178nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1179    `foot:' |             Size of chunk, in bytes                           | 1180	    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1181 1182    The P (PREV_INUSE) bit, stored in the unused low-order bit of the 1183    chunk size (which is always a multiple of two words), is an in-use 1184    bit for the *previous* chunk.  If that bit is *clear*, then the 1185    word before the current chunk size contains the previous chunk 1186    size, and can be used to find the front of the previous chunk. 1187    The very first chunk allocated always has this bit set, 1188    preventing access to non-existent (or non-owned) memory. If 1189    prev_inuse is set for any given chunk, then you CANNOT determine 1190    the size of the previous chunk, and might even get a memory 1191    addressing fault when trying to do so. 1192 1193    Note that the `foot' of the current chunk is actually represented 1194    as the prev_size of the NEXT chunk. This makes it easier to 1195    deal with alignments etc but can be very confusing when trying 1196    to extend or adapt this code. 1197 1198    The two exceptions to all this are 1199 1200     1. The special chunk `top' doesn't bother using the 1201	trailing size field since there is no next contiguous chunk 1202	that would have to index off it. After initialization, `top' 1203	is forced to always exist.  If it would become less than 1204	MINSIZE bytes long, it is replenished. 1205 1206     2. Chunks allocated via mmap, which have the second-lowest-order 1207	bit M (IS_MMAPPED) set in their size fields.  Because they are 1208	allocated one-by-one, each must contain its own trailing size field. 1209 1210*/ 1211

老老实实记录下大小不就行了？如果能通过指针直接获取指向空间的大小，那还是c++么，成java了

_mem_control_block是自己定义的一个结构体，用来管理申请内存前面的那16个字节 当你申请一段10字节空间的时候，编译器实际会占用的字节为 【申请空间的头信息】【实际申请到的空间】  【申请空间的头信息】其实就是上面说到的那16个字节，我只是用_mem_control_block这个结构体来表示这16个字节而已。 【实际申请到的空间】某些平台这个区域长度与实际长度可能不一致辞，如你申请10个字节，在某些编译器为了字节对齐下会分配12（4字节对齐）个或16（8字节对齐）个字节。函数返回的指针是该区域的首地址。

把new到的指针地址前面8个地址的值都打印出来，数据长度应该在那里面 多测试几组找一下规律，不同编译器不一样

VMMap 是进程虚拟和物理内存分析实用工具。http://technet.microsoft.com/zh-cn/sysinternals/dd535533

就从语言特性上面来说，是不支持的，换句话说，编译器也做不到，比如什么sizeof(*p)之类的。  从code角度或者从操作系统角度来说，是可以的。比如说在用户申请的内存，加上内存头，内存尾等。中间可以加一堆调试信息。  而这些都是代码层面的。

引用 10 楼 xiaohuh421 的回复:new出来的内存是可以得到分配大小的.  实际就是在数据区的前面.  A *pA = new A[11]; A *pCopyA = pA; int nCount = *((int *)pCopyA-1);  //这里就可以取得分配的元素个数.  (注意, 是元素个数, 不是字节数)  delete [] pA;这做法是错的 别误人子弟啊

引用 11 楼 wangyaninglm 的回复:[quote=引用 10 楼 xiaohuh421 的回复:] new出来的内存是可以得到分配大小的.  实际就是在数据区的前面.  A *pA = new A[11]; A *pCopyA = pA; int nCount = *((int *)pCopyA-1);  //这里就可以取得分配的元素个数.  (注意, 是元素个数, 不是字节数)  delete [] pA;  请问这么写的原理是啥，没看懂[/quote]  引用 15 楼 zhangxiangDavaid 的回复:经验证，10楼的不对  怪我没有说明使用此方法的条件. 使用这种方法计算大小, 需要满足以下条件. 1. 必需是以new[] 来分配的内存. 2. 必需是自定义类型, 不能是基本数据类型.  如果要计算基本数据类型的大小. 需要使用这里说的.方法http://blog.csdn.net/will_hsbsch/article/details/21124055  下面这个也可以参考: http://blog.sina.com.cn/s/blog_6a820b3c0100lbyl.html  其原理都是一样.  利用内存管理结构的特殊性.  特别注意: 可能不同的IDE或者不同的操作系统可能导致不同,   因为内存管理机制可能不同.  size_t _msize(    void *memblock  ); 对于malloc系列的函数是可用的. 但对于new[]出的,   在VS2008中是崩溃. 不能得出大小. 它的原理是:http://blog.sina.com.cn/s/blog_6a820b3c0100lbyl.html debug环境下代码如下:  extern "C" _CRTIMP size_t __cdecl _msize_dbg (         void * pUserData,         int nBlockUse         ) {         size_t nSize;         _CrtMemBlockHeader * pHead;          /* validation section */         _VALIDATE_RETURN(pUserData != NULL, EINVAL, -1);          /* verify heap before getting size */         if (check_frequency > 0)             if (check_counter == (check_frequency - 1))             {                 _ASSERTE(_CrtCheckMemory());                 check_counter = 0;             }             else                 check_counter++;          _mlock(_HEAP_LOCK);         /* block other threads */         __try {          /*          * If this ASSERT fails, a bad pointer has been passed in. It may be          * totally bogus, or it may have been allocated from another heap.          * The pointer MUST come from the 'local' heap.          */         _ASSERTE(_CrtIsValidHeapPointer(pUserData));          /* get a pointer to memory block header */         pHead = pHdr(pUserData);           /* verify block type */         _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));          /* CRT blocks can be treated as NORMAL blocks */         if (pHead->nBlockUse == _CRT_BLOCK && nBlockUse == _NORMAL_BLOCK)             nBlockUse = _CRT_BLOCK;  /* The following assertion was prone to false positives - JWM */ /*        if (pHead->nBlockUse != _IGNORE_BLOCK)              */ /*            _ASSERTE(pHead->nBlockUse == nBlockUse);        */          nSize = pHead->nDataSize;          }         __finally {             _munlock(_HEAP_LOCK);   /* release other threads */         }          return nSize; }

引用 28 楼 xihu1364 的回复:[quote=引用 25 楼 lin5161678 的回复:] [quote=引用 24 楼 xiaohuh421 的回复:] [quote=引用 22 楼 lin5161678 的回复:] 这做法是错的 别误人子弟啊  请看21楼 [/quote]21楼依然没说对  使用这种方法计算大小, 需要满足以下条件. 1. 必需是以new[] 来分配的内存. 2. 必需是自定义类型, 不能是基本数据类型.  还有一个条件3  分配策略 会在分配的内存前面记录分配数量 这个条件3至关重要[/quote]  这只是分配策略的问题，但是21楼说的这个思路是一种内存的分配策略  但是你自己去分配的大小都不记，那你搞毛啊！系统已经帮你在delete的时候 delete[] 省去了传入大小[/quote] 不知道你在说些什么  21楼说了一个分配策略 但是 实际的分配策略未必如21楼所说 所以 21楼所说的内容要成立 必须要有一个重要前提  必须假定 分配策略一定是这样 后面的说法才有意义  然后 自己分配的大小记不记 是楼主的事 和我没关系  和分配策略也没关系 你在喷啥? 先把靶子摆好吧

引用 31 楼 wangyaninglm 的回复:[quote=引用 28 楼 xihu1364 的回复:] [quote=引用 25 楼 lin5161678 的回复:] [quote=引用 24 楼 xiaohuh421 的回复:] [quote=引用 22 楼 lin5161678 的回复:] 这做法是错的 别误人子弟啊  请看21楼 [/quote]21楼依然没说对  使用这种方法计算大小, 需要满足以下条件. 1. 必需是以new[] 来分配的内存. 2. 必需是自定义类型, 不能是基本数据类型.  还有一个条件3  分配策略 会在分配的内存前面记录分配数量 这个条件3至关重要[/quote]  这只是分配策略的问题，但是21楼说的这个思路是一种内存的分配策略  但是你自己去分配的大小都不记，那你搞毛啊！系统已经帮你在delete的时候 delete[] 省去了传入大小[/quote]  那为啥delete可以不用指定大小？[/quote]  如有的分配策略是  malloc  传入大小 返回 指针         如：大小为12    真实分配内存是大于12，因为需要保存大小等信息，有可能是2个字节，有可能是4个字节等等....  所以free的时候就可以得到大小  而我们是不确定分配策略的

new里面自动调用各层继承类的构造函数 delete里面自动调用各层继承类的析构函数 类的实例是对象，不是一段内存，求其BYTE*指针指向内存的大小本身就是一个伪命题。 我觉得。  《深度探索C++对象模型》 《C++反汇编与逆向分析技术揭秘》


Question: char

、。。。、。。、、。。、O(∩_∩)O  谢谢

2楼正解：'10' == 49 * 256 + 48 == 12592

- -!!! 现在的小朋友是不是象力越来越丰富了... // ---------------------------------------------------------- '10' 不等 10 对于直接那 'xxxx' 多字节符来作运算,编译器会把内存内容做作一个int来处理 如 '10', 即两个字节 '1'  '0' ,   '1' 的 ascii 码为49   '0'为48,那么 '10' == 49 * 256 + 48 == 12592 ch1 == '3' == 51  (ascii 码) n1 = ch1 - '10'  即  51 - 12592 == -12541  .... ... // ------------------------------------------------------- 当然不是你想要的结果啦..

n1 = ch1 - '\10'; 	n1 = ch1 - 10; 	n1 = ch1 - 0x10; 	n1 = ch1 - 010;


Question: 关于c语言编程获取bios中的温度数据的方法。请高手指点。

这个域名打不开呀。

引用 1 楼 user-2 的回复:有个open-hardware-monitor开源工具，不过是C#的，不知道你能看懂不。 源码地址：https://code.google.com/p/open-hardware-monitor/ 一楼的，域名被墙了吧！

引用 3 楼 joyson2015 的回复:这个域名打不开呀。  打不开就在csdn下载里搜吧


Question: C语言实现 字符串转化为 16进制整形数据？

引用 25 楼 sholber 的回复:[quote=引用 24 楼 vnvlyp 的回复:] [quote=引用 18 楼 sholber 的回复:] [quote=引用 16 楼 vnvlyp 的回复:] [quote=引用 10 楼 sholber 的回复:] 多数字符都都兼容ASCII，但也有个别例外。最典型的就是 EBCDIC，字符f的编码是134。而且，英文字母在表中并不是连续的，但好在C并没有规定a~z和A~Z必须连续，只规定'0'~'9'必须是连续的。 EBCDIC也就IBM古董机之类的才用吧。。现代计算机还没有不支持或兼容ASCII的吧？[/quote] 制定C标准的时候估计发生过类似的争论。。。但实际上是，C要求的是兼容并蓄，不是因为多就无视少。很多错误和事故就是因为当初觉得不可能发生。[/quote] 我的意思是除非你是专门给古董机写程序，不然考虑这个问题没有必要吧。。反正你现在写的程序也不可能放到什么古董机上运行[/quote] 这种认识是不对的。 1，那不是古董。计算机行业里，谁也说不准哪天会碰到，或者需要一些特殊的机器，有可能是新造的。流行不代表“新”，偏门的应用不代表“旧”。有需求的地方，什么事情都会发生。哪天有个大老板出100万让你写一个程序，它的目标小设备就是个奇怪的字符集（符合C标准要求，但不兼容ASCII），你说那是古董机，爷不挣这个钱？ 2，如果你的代码不是可移值的，不是依从C标准的，应当有所说明。就像微软的软件，适用什么处理器，多大内存需求，需要什么操作系统支持之类的。如果不说明，只因为流行，这是误导。本来学生们视界就窄，如果顺势错误地鼓励而不是告诉他们实际是什么情况，他们一辈子就怀着错误的认识写程序。[/quote] 新造的机器除非是某些特定行业用的微控什么的不需要ASCII，不然没有必要故意去不兼容ASCII吧？除非你从底层硬件，操作系统开始做一套全新的系统，不然现行广泛采用的解决方法还没有不支持ASCII的吧？但是谁又会放弃几十年的开发积累又从空白开始做起？ 至于C标准和可移植性，这个问题我觉得是有争议的，第一，选择只兼容那些兼容ASCII的字符集，在移植性上我觉得没有什么大问题，因为基本上能跑现代程序的也都兼容ASCII，第二，完全兼容C标准我觉得在现实中代价太大，更普遍的是针对特定群体开发，特别是当程序达到一定规模基本上就不可能完全兼容所有C认为需要兼容的系统和机器，第三，至于误导初学者这个不能叫误导吧？比如你肯定不会在崎岖不平的路上教小孩走路，平路都走不稳怎么走得好各种坑洼，但是不是代表着在平路上教走路就是误导呢？或者在平路上学会走路的以后在不平的路上走就会摔死呢？初学者基本概念都不清楚，你就说要考虑这考虑那，那基本上也只是莫名其妙完全不知所云，这些问题随着学习深入再接触也不是什么大问题吧？如果他们一辈子再也没接触到这个问题，怀着不完整的观点写程序，那也只能说是个人造化问题，毕竟水平是会有三六九等的。

作为一个C程序员，对  scanf,sscanf,fscanf  printf,sprintf,fprintf 这类函数的用法，还是要做到“拳不离手，曲不离口”的。

引用 18 楼 sholber 的回复:[quote=引用 16 楼 vnvlyp 的回复:] [quote=引用 10 楼 sholber 的回复:] [quote=引用 8 楼 jiht594 的回复:] [quote=引用 7 楼 sholber 的回复:] [quote=引用 5 楼 user-9 的回复:]  int str2int(char *str) { 	int n=0; 	while(*str) 	{ 		n<<=4; 		if(*str<='9') 			n|=*str-'0'; 		else 			n|=(*str&~0x20)-'A'+10; 		++str; 	} 	return n; }  引用 6 楼 jiht594 的回复:正常来说, 字符'f'对应十进制101, 十六进制的0x66  你想把f变成十进制的15(也就是16进制的0xf)??  你们是在讨论ASCII？ C没规定必须用 ASCII，也没说26个英文字母在字符集中必须连续。除非楼主说就限定使用ASCII的转换环境和执行环境。[/quote]  不好意思.  我接触的c/c++, 也就是咱们这个论坛的名字, 字符串中的f不是十进制101, 十六进制的0x66吗?? 求教[/quote] 多数字符都都兼容ASCII，但也有个别例外。最典型的就是 EBCDIC，字符f的编码是134。而且，英文字母在表中并不是连续的，但好在C并没有规定a~z和A~Z必须连续，只规定'0'~'9'必须是连续的。[/quote] EBCDIC也就IBM古董机之类的才用吧。。现代计算机还没有不支持或兼容ASCII的吧？[/quote] 制定C标准的时候估计发生过类似的争论。。。但实际上是，C要求的是兼容并蓄，不是因为多就无视少。很多错误和事故就是因为当初觉得不可能发生。[/quote] 我的意思是除非你是专门给古董机写程序，不然考虑这个问题没有必要吧。。反正你现在写的程序也不可能放到什么古董机上运行

引用 24 楼 vnvlyp 的回复:[quote=引用 18 楼 sholber 的回复:] [quote=引用 16 楼 vnvlyp 的回复:] [quote=引用 10 楼 sholber 的回复:] [quote=引用 8 楼 jiht594 的回复:] [quote=引用 7 楼 sholber 的回复:] [quote=引用 5 楼 user-9 的回复:]  int str2int(char *str) { 	int n=0; 	while(*str) 	{ 		n<<=4; 		if(*str<='9') 			n|=*str-'0'; 		else 			n|=(*str&~0x20)-'A'+10; 		++str; 	} 	return n; }  引用 6 楼 jiht594 的回复:正常来说, 字符'f'对应十进制101, 十六进制的0x66  你想把f变成十进制的15(也就是16进制的0xf)??  你们是在讨论ASCII？ C没规定必须用 ASCII，也没说26个英文字母在字符集中必须连续。除非楼主说就限定使用ASCII的转换环境和执行环境。[/quote]  不好意思.  我接触的c/c++, 也就是咱们这个论坛的名字, 字符串中的f不是十进制101, 十六进制的0x66吗?? 求教[/quote] 多数字符都都兼容ASCII，但也有个别例外。最典型的就是 EBCDIC，字符f的编码是134。而且，英文字母在表中并不是连续的，但好在C并没有规定a~z和A~Z必须连续，只规定'0'~'9'必须是连续的。[/quote] EBCDIC也就IBM古董机之类的才用吧。。现代计算机还没有不支持或兼容ASCII的吧？[/quote] 制定C标准的时候估计发生过类似的争论。。。但实际上是，C要求的是兼容并蓄，不是因为多就无视少。很多错误和事故就是因为当初觉得不可能发生。[/quote] 我的意思是除非你是专门给古董机写程序，不然考虑这个问题没有必要吧。。反正你现在写的程序也不可能放到什么古董机上运行[/quote] 这种认识是不对的。 1，那不是古董。计算机行业里，谁也说不准哪天会碰到，或者需要一些特殊的机器，有可能是新造的。流行不代表“新”，偏门的应用不代表“旧”。有需求的地方，什么事情都会发生。哪天有个大老板出100万让你写一个程序，它的目标小设备就是个奇怪的字符集（符合C标准要求，但不兼容ASCII），你说那是古董机，爷不挣这个钱？ 2，如果你的代码不是可移值的，不是依从C标准的，应当有所说明。就像微软的软件，适用什么处理器，多大内存需求，需要什么操作系统支持之类的。如果不说明，只因为流行，这是误导。本来学生们视界就窄，如果顺势错误地鼓励而不是告诉他们实际是什么情况，他们一辈子就怀着错误的认识写程序。

引用 6 楼 jiht594 的回复:正常来说, 字符'f'对应十进制101, 十六进制的0x66  你想把f变成十进制的15(也就是16进制的0xf)??  是这个意思。

引用 5 楼 user-9 的回复: int str2int(char *str) { 	int n=0; 	while(*str) 	{ 		n<<=4; 		if(*str<='9') 			n|=*str-'0'; 		else 			n|=(*str&~0x20)-'A'+10; 		++str; 	} 	return n; }  引用 5 楼 user-9 的回复: int str2int(char *str) { 	int n=0; 	while(*str) 	{ 		n<<=4; 		if(*str<='9') 			n|=*str-'0'; 		else 			n|=(*str&~0x20)-'A'+10; 		++str; 	} 	return n; }   谢谢，我试一试

#include <stdio.h> #include <stdlib.h>  int main() {     char buffer[20];     long n;     FILE* fp;     fp = fopen("test.txt","r");     FILE* out = fopen("out.txt","w");     if(!fp)     {         fprintf(stderr , "can`t open file\n");         exit(0);     }     while((fscanf(fp , "%s" , buffer))== 1)           {               sscanf(buffer , "%x" , &n);               fprintf(out,"%-5d\n" , n);           }     fclose(fp);     fclose(out);     printf("%d\n",n);     return 0; }

#include <stdio.h>  int main() {     char buffer[20];     long n;     fgets(buffer , 19 , stdin);     sscanf(buffer, "%x" , &n);     printf("%d\n",n);     return 0; }

引用 16 楼 vnvlyp 的回复:[quote=引用 10 楼 sholber 的回复:] [quote=引用 8 楼 jiht594 的回复:] [quote=引用 7 楼 sholber 的回复:] [quote=引用 5 楼 user-9 的回复:]  int str2int(char *str) { 	int n=0; 	while(*str) 	{ 		n<<=4; 		if(*str<='9') 			n|=*str-'0'; 		else 			n|=(*str&~0x20)-'A'+10; 		++str; 	} 	return n; }  引用 6 楼 jiht594 的回复:正常来说, 字符'f'对应十进制101, 十六进制的0x66  你想把f变成十进制的15(也就是16进制的0xf)??  你们是在讨论ASCII？ C没规定必须用 ASCII，也没说26个英文字母在字符集中必须连续。除非楼主说就限定使用ASCII的转换环境和执行环境。[/quote]  不好意思.  我接触的c/c++, 也就是咱们这个论坛的名字, 字符串中的f不是十进制101, 十六进制的0x66吗?? 求教[/quote] 多数字符都都兼容ASCII，但也有个别例外。最典型的就是 EBCDIC，字符f的编码是134。而且，英文字母在表中并不是连续的，但好在C并没有规定a~z和A~Z必须连续，只规定'0'~'9'必须是连续的。[/quote] EBCDIC也就IBM古董机之类的才用吧。。现代计算机还没有不支持或兼容ASCII的吧？[/quote] 制定C标准的时候估计发生过类似的争论。。。但实际上是，C要求的是兼容并蓄，不是因为多就无视少。很多错误和事故就是因为当初觉得不可能发生。

引用 11 楼 user-9 的回复:[quote=引用 9 楼 jiht594 的回复:] [quote=引用 8 楼 jiht594 的回复:] [quote=引用 7 楼 sholber 的回复:] [quote=引用 5 楼 user-9 的回复:]  int str2int(char *str) { 	int n=0; 	while(*str) 	{ 		n<<=4; 		if(*str<='9') 			n|=*str-'0'; 		else 			n|=(*str&~0x20)-'A'+10; 		++str; 	} 	return n; }  引用 6 楼 jiht594 的回复:正常来说, 字符'f'对应十进制101, 十六进制的0x66  你想把f变成十进制的15(也就是16进制的0xf)??  你们是在讨论ASCII？ C没规定必须用 ASCII，也没说26个英文字母在字符集中必须连续。除非楼主说就限定使用ASCII的转换环境和执行环境。[/quote]  不好意思.  我接触的c/c++, 也就是咱们这个论坛的名字, 字符串中的f不是十进制101, 十六进制的0x66吗?? 求教[/quote] 我收回我说的话,承认错误. 确实没遇见过非ascii编码的[/quote] 如果你想要非ASCII编码的话，可以用全角的数字和字母，虽然数字和字母各自依然还是连续的。[/quote] 两回事。 你想得简单了。你可能还没听说过基本字符集和扩展字符集。C要求基本字符集里必须至少包含哪些字符，但还没要求基本字符集里有什么全角半角字符。

引用 10 楼 sholber 的回复:[quote=引用 8 楼 jiht594 的回复:] [quote=引用 7 楼 sholber 的回复:] [quote=引用 5 楼 user-9 的回复:]  int str2int(char *str) { 	int n=0; 	while(*str) 	{ 		n<<=4; 		if(*str<='9') 			n|=*str-'0'; 		else 			n|=(*str&~0x20)-'A'+10; 		++str; 	} 	return n; }  引用 6 楼 jiht594 的回复:正常来说, 字符'f'对应十进制101, 十六进制的0x66  你想把f变成十进制的15(也就是16进制的0xf)??  你们是在讨论ASCII？ C没规定必须用 ASCII，也没说26个英文字母在字符集中必须连续。除非楼主说就限定使用ASCII的转换环境和执行环境。[/quote]  不好意思.  我接触的c/c++, 也就是咱们这个论坛的名字, 字符串中的f不是十进制101, 十六进制的0x66吗?? 求教[/quote] 多数字符都都兼容ASCII，但也有个别例外。最典型的就是 EBCDIC，字符f的编码是134。而且，英文字母在表中并不是连续的，但好在C并没有规定a~z和A~Z必须连续，只规定'0'~'9'必须是连续的。[/quote] EBCDIC也就IBM古董机之类的才用吧。。现代计算机还没有不支持或兼容ASCII的吧？

仅供参考：  #include <stdlib.h> #include <stdio.h> int main(void) { 	char *str = "f2"; 	puts(str); 	char *e; 	long l = strtol(str, &e, 16);  //字符串转十进制 	printf("l=%d\n", l); 	char dest[9]; 	_ltoa(l, dest, 16);   //十进制整数转十六进制 	printf("dest=%s\n", dest); 	return 0; } //f2 //l=242 //dest=f2

仅供参考：  #include<stdio.h> int main(void)   //13 { 	char *str = "f2"; 	puts(str); 	long l; 	sscanf(str, "%x", &l);   //字符串转十进制 	printf("l=%d\n", l);     //按十进制打印 	printf("l=%x\n", l);     //按十六进制打印 	system("pause"); 	return 0; } //f2 //l=242 //l=f2

引用 11 楼 user-9 的回复:如果你想要非ASCII编码的话，可以用全角的数字和字母，虽然数字和字母各自依然还是连续的。 这个也算是.  我的意思是那种默认的编码?

(*str&~0x20)转小写差点没看出来，就差值域检测了

引用 9 楼 jiht594 的回复:[quote=引用 8 楼 jiht594 的回复:] [quote=引用 7 楼 sholber 的回复:] [quote=引用 5 楼 user-9 的回复:]  int str2int(char *str) { 	int n=0; 	while(*str) 	{ 		n<<=4; 		if(*str<='9') 			n|=*str-'0'; 		else 			n|=(*str&~0x20)-'A'+10; 		++str; 	} 	return n; }  引用 6 楼 jiht594 的回复:正常来说, 字符'f'对应十进制101, 十六进制的0x66  你想把f变成十进制的15(也就是16进制的0xf)??  你们是在讨论ASCII？ C没规定必须用 ASCII，也没说26个英文字母在字符集中必须连续。除非楼主说就限定使用ASCII的转换环境和执行环境。[/quote]  不好意思.  我接触的c/c++, 也就是咱们这个论坛的名字, 字符串中的f不是十进制101, 十六进制的0x66吗?? 求教[/quote] 我收回我说的话,承认错误. 确实没遇见过非ascii编码的[/quote] 如果你想要非ASCII编码的话，可以用全角的数字和字母，虽然数字和字母各自依然还是连续的。

引用 8 楼 jiht594 的回复:[quote=引用 7 楼 sholber 的回复:] [quote=引用 5 楼 user-9 的回复:]  int str2int(char *str) { 	int n=0; 	while(*str) 	{ 		n<<=4; 		if(*str<='9') 			n|=*str-'0'; 		else 			n|=(*str&~0x20)-'A'+10; 		++str; 	} 	return n; }  引用 6 楼 jiht594 的回复:正常来说, 字符'f'对应十进制101, 十六进制的0x66  你想把f变成十进制的15(也就是16进制的0xf)??  你们是在讨论ASCII？ C没规定必须用 ASCII，也没说26个英文字母在字符集中必须连续。除非楼主说就限定使用ASCII的转换环境和执行环境。[/quote]  不好意思.  我接触的c/c++, 也就是咱们这个论坛的名字, 字符串中的f不是十进制101, 十六进制的0x66吗?? 求教[/quote] 多数字符都都兼容ASCII，但也有个别例外。最典型的就是 EBCDIC，字符f的编码是134。而且，英文字母在表中并不是连续的，但好在C并没有规定a~z和A~Z必须连续，只规定'0'~'9'必须是连续的。

引用 8 楼 jiht594 的回复:[quote=引用 7 楼 sholber 的回复:] [quote=引用 5 楼 user-9 的回复:]  int str2int(char *str) { 	int n=0; 	while(*str) 	{ 		n<<=4; 		if(*str<='9') 			n|=*str-'0'; 		else 			n|=(*str&~0x20)-'A'+10; 		++str; 	} 	return n; }  引用 6 楼 jiht594 的回复:正常来说, 字符'f'对应十进制101, 十六进制的0x66  你想把f变成十进制的15(也就是16进制的0xf)??  你们是在讨论ASCII？ C没规定必须用 ASCII，也没说26个英文字母在字符集中必须连续。除非楼主说就限定使用ASCII的转换环境和执行环境。[/quote]  不好意思.  我接触的c/c++, 也就是咱们这个论坛的名字, 字符串中的f不是十进制101, 十六进制的0x66吗?? 求教[/quote] 我收回我说的话,承认错误. 确实没遇见过非ascii编码的

引用 7 楼 sholber 的回复:[quote=引用 5 楼 user-9 的回复:]  int str2int(char *str) { 	int n=0; 	while(*str) 	{ 		n<<=4; 		if(*str<='9') 			n|=*str-'0'; 		else 			n|=(*str&~0x20)-'A'+10; 		++str; 	} 	return n; }  引用 6 楼 jiht594 的回复:正常来说, 字符'f'对应十进制101, 十六进制的0x66  你想把f变成十进制的15(也就是16进制的0xf)??  你们是在讨论ASCII？ C没规定必须用 ASCII，也没说26个英文字母在字符集中必须连续。除非楼主说就限定使用ASCII的转换环境和执行环境。[/quote]  不好意思.  我接触的c/c++, 也就是咱们这个论坛的名字, 字符串中的f不是十进制101, 十六进制的0x66吗?? 求教


Question: libcurl的回调函数中将收到HTTP Body赋值给全局变量

你这个程序有很多问题： 1、35行申请内存cresult，36行又把buffer赋给cresult，这样第35行申请的内存就泄露了。 2、每次解析HTTP Body libcurl都会有一个内存区域来存放Body，然后调用回调函数write_func，第一个参数buffer就是存放Body的指针，每次你都把buffer指针赋给cresult，所以第34行free的其实是buffer而不是第35行申请的内存，如果buffer是栈内存而不是堆内存的话，程序将可能coredump。 3、第63行curl_easy_cleanup之后应该会释放libcurl库内部申请的内存，包括存放HTTP Body的buffer，所以会出现你所说的问题。 4、第33行和第66行的锁不是这么用的，你得清楚你要锁什么，尽量不要把加锁和解锁放到两个不同的函数中，尽量把锁的粒度压到最小。

没用过这个库 我猜有可能过了生存周期释放了，你memcpy吧。


Question: 求Linux 下c语言实践项目书籍

《Linux C编程一站式学习》

百度DMS电信计费系统， 练习使用C\S架构， 生产者消费之模型，线程池等技术。


Question: C语言文件比较问题

引用 4 楼 zhangxiangDavaid 的回复:if (MAXLINES2 == 1280000) MAXLINES2 = 2500000; 这一句有特别的含义吗？ 被发现了。 当年调试到此时，发现我的破电脑2560000分配不了，2500000可以。

引用 7 楼 u013163178 的回复:#include <stdio.h> #include <stdlib.h>  int file_size(FILE* fp) {     long mark = ftell(fp);     int size;     fseek(fp , 0 , SEEK_END);     size = ftell(fp);     fseek(fp , mark , SEEK_SET);     return size; } int main() {     FILE* f1 , *f2;     FILE* logs;     logs = fopen("log.txt" , "a+");     f1 = fopen("f1.txt" , "r");     f2 = fopen("f2.txt" , "r");      if(!logs)     {         fprintf(stderr , "can`t open log.txt\n");         exit(EXIT_FAILURE);     }     if(!f1)         {             fprintf(logs , "can`t open f1.txt\n");             exit(EXIT_FAILURE);         }     if(!f1)     {         fprintf(logs , "can`t open f2.txt");         exit(EXIT_FAILURE);     }      int a , b;     long n = 0;     size_t s1 , s2;     s1 = file_size(f1);     s2 = file_size(f2);     //比较文件的size     if(s1 != s2)         fprintf(logs,"file size not equel.\n");       //将文件的内容读到内存进行比较     while((a = fgetc(f1)) != EOF && (b = fgetc(f2)) != EOF)     {         n++;         if(a == b)             continue;         else         fprintf(logs, "%ldth byte not equel\n",n);     }       fclose(f1);     fclose(f2);     fclose(logs);     return 0; }  谢谢了，我之前想的是为用户输入的用户名和密码创建一个txt格式的文件，将其与存储好的文本进行比较，但是后来觉得有些多此一举，就想直接让输入的信心与文本进行比较，请问这样如何实现呢？

1.将文本内容读入到内存到，数据在内存中什么形式存放，看你个人，hash，数组什么的都可以。 2.查找即可。

对一楼的注释：  #define MAXCHARS 512 int MAXLINES = 10000, MAXLINES2; char *buf, *buf2; char PROG[256] = "PROG";//程序Program需要的文件列表 char LIST[256] = "LIST";//dir /b /s生成的实际文件列表List FILE *fp, *fl; int i, c, n, L, hh; int ignore_case = 0; char ln[MAXCHARS]; int icompare(const void *arg1, const void *arg2) { 	return stricmp((char *)arg1, (char *)arg2); } int compare(const void *arg1, const void *arg2) { 	return strcmp((char *)arg1, (char *)arg2); } int main(int argc, char **argv) { 	if (argc>1) strcpy(PROG, argv[1]);//命令行参数1覆盖PROG 	if (argc>2) strcpy(LIST, argv[2]);//命令行参数2覆盖LIST 	if (argc>3) ignore_case = 1;//若存在命令行参数3，忽略大小写 	if ((fl = fopen(LIST, "rt")) == NULL) { 		fprintf(stderr, "Can not open %s\n", LIST); 		fprintf(stderr, "Usage: %s [PROG] [LIST] [-i]\n", argv[0]); 		return 1; 	} 	if ((fp = fopen(PROG, "rt")) == NULL) { 		fclose(fl); 		fprintf(stderr, "Can not open %s\n", PROG); 		fprintf(stderr, "Usage: %s [PROG] [LIST] [-i]\n", argv[0]); 		return 2; 	} 	buf = (char *)malloc(MAXLINES*MAXCHARS); 	if (NULL == buf) { 		fclose(fl); 		fclose(fp); 		fprintf(stderr, "Can not malloc(%d LINES*%d CHARS)!\n", MAXLINES, MAXCHARS); 		return 4; 	} 	n = 0; 	hh = 0; 	i = 0;     //把LIST中的所有行读入到buf中 	while (1) { 		if (fgets(ln, MAXCHARS, fl) == NULL) break;// 		hh++; 		L = strlen(ln) - 1; 		if ('\n' != ln[L]) {////有限行最后一个字符是'\n',超长行忽略后面内容 			fprintf(stderr, "%s Line %d too long(>%d),spilth ignored.\n", LIST, hh, MAXCHARS); 			while (1) {//继续把超长行读完 				c = fgetc(fl); 				if ('\n' == c || EOF == c) break;//读到'\n'或文件结束符，即表明读完 			} 		} 		while (1) {//去掉行尾的'\n'和空格 			if ('\n' == ln[L] || ' ' == ln[L]) { 				ln[L] = 0; 				L--; 				if (L<0) break;//空行 			} 			else break;// 		} 		if (L >= 0) { 			strcpy(buf + i, ln); i += MAXCHARS; 			n++;             //若buf的空间不够，就扩充 			if (n >= MAXLINES) { 				MAXLINES2 = MAXLINES * 2; 				if (MAXLINES2 == 1280000) MAXLINES2 = 2500000; 				buf2 = (char *)realloc(buf, MAXLINES2*MAXCHARS); 				if (NULL == buf2) { 					free(buf); 					fclose(fl); 					fclose(fp); 					fprintf(stderr, "Can not malloc(%d LINES*%d CHARS)!\n", MAXLINES2, MAXCHARS); 					return 5; 				} 				buf = buf2; 				MAXLINES = MAXLINES2; 			} 		} 	} 	fclose(fl);     //使用快速排序 	if (ignore_case) qsort(buf, n, MAXCHARS, icompare); 	else qsort(buf, n, MAXCHARS, compare); 	hh = 0;     //读取PROG中内容 	while (1) { 		if (fgets(ln, MAXCHARS, fp) == NULL) break;// 		hh++; 		L = strlen(ln) - 1; 		if ('\n' != ln[L]) {////有限行最后一个字符是'\n',超长行忽略后面内容 			fprintf(stderr, "%s Line %d too long(>%d),spilth ignored.\n", PROG, hh, MAXCHARS); 			while (1) { 				c = fgetc(fp); 				if ('\n' == c || EOF == c) break;//读到'\n'或文件结束符，即表明读完 			} 		} 		while (1) {//去掉行尾的'\n'和空格 			if ('\n' == ln[L] || ' ' == ln[L]) { 				ln[L] = 0; 				L--; 				if (L<0) break;// 			} 			else break;// 		} 		if (L >= 0) { 			if (ignore_case) { 				if (NULL == bsearch(ln, buf, n, MAXCHARS, icompare)) printf("%s\n", ln); 			} 			else { 				if (NULL == bsearch(ln, buf, n, MAXCHARS, compare)) printf("%s\n", ln); 			} 		} 	} 	fclose(fp); 	free(buf); 	return 0; }

内存中比较啦～

赵老师总是舍不得多敲几个空格和回车，代码挤在一起，看起来很累，坏眼睛啊

凡是不超过200行的代码都不能称之为复杂的代码。

老师，请问您有更简单些的代码示例吗？我只学半年C语言，这种代码有些高深啊TT，做完实验我们就学JAVA了。。。

仅供参考：//输出PROG中有但LIST中没有的文本行，即集合PROG-LIST #include <stdio.h> #include <string.h> #include <stdlib.h> #include <search.h> #define MAXCHARS 512 int MAXLINES=10000,MAXLINES2; char *buf,*buf2; char PROG[256]="PROG";//程序Program需要的文件列表 char LIST[256]="LIST";//dir /b /s生成的实际文件列表List FILE *fp,*fl; int i,c,n,L,hh; int ignore_case=0; char ln[MAXCHARS]; int icompare(const void *arg1,const void *arg2) {    return stricmp((char *)arg1,(char *)arg2); } int compare(const void *arg1,const void *arg2) {    return strcmp((char *)arg1,(char *)arg2); } int main(int argc,char **argv) {     if (argc>1) strcpy(PROG,argv[1]);//命令行参数1覆盖PROG     if (argc>2) strcpy(LIST,argv[2]);//命令行参数2覆盖LIST     if (argc>3) ignore_case=1;//若存在命令行参数3，忽略大小写     if ((fl=fopen(LIST,"rt"))==NULL) {         fprintf(stderr,"Can not open %s\n",LIST);         fprintf(stderr,"Usage: %s [PROG] [LIST] [-i]\n",argv[0]);         return 1;     }     if ((fp=fopen(PROG,"rt"))==NULL) {         fclose(fl);         fprintf(stderr,"Can not open %s\n",PROG);         fprintf(stderr,"Usage: %s [PROG] [LIST] [-i]\n",argv[0]);         return 2;     }     buf=(char *)malloc(MAXLINES*MAXCHARS);     if (NULL==buf) {         fclose(fl);         fclose(fp);         fprintf(stderr,"Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES,MAXCHARS);         return 4;     }     n=0;     hh=0;     i=0;     while (1) {         if (fgets(ln,MAXCHARS,fl)==NULL) break;//         hh++;         L=strlen(ln)-1;         if ('\n'!=ln[L]) {//超长行忽略后面内容             fprintf(stderr,"%s Line %d too long(>%d),spilth ignored.\n",LIST,hh,MAXCHARS);             while (1) {                 c=fgetc(fl);                 if ('\n'==c || EOF==c) break;//             }         }         while (1) {//去掉行尾的'\n'和空格             if ('\n'==ln[L] || ' '==ln[L]) {                 ln[L]=0;                 L--;                 if (L<0) break;//             } else break;//         }         if (L>=0) {             strcpy(buf+i,ln);i+=MAXCHARS;             n++;             if (n>=MAXLINES) {                 MAXLINES2=MAXLINES*2;                 if (MAXLINES2==1280000) MAXLINES2=2500000;                 buf2=(char *)realloc(buf,MAXLINES2*MAXCHARS);                 if (NULL==buf2) {                     free(buf);                     fclose(fl);                     fclose(fp);                     fprintf(stderr,"Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES2,MAXCHARS);                     return 5;                 }                 buf=buf2;                 MAXLINES=MAXLINES2;             }         }     }     fclose(fl);     if (ignore_case) qsort(buf,n,MAXCHARS,icompare);     else qsort(buf,n,MAXCHARS,compare);     hh=0;     while (1) {         if (fgets(ln,MAXCHARS,fp)==NULL) break;//         hh++;         L=strlen(ln)-1;         if ('\n'!=ln[L]) {//超长行忽略后面内容             fprintf(stderr,"%s Line %d too long(>%d),spilth ignored.\n",PROG,hh,MAXCHARS);             while (1) {                 c=fgetc(fp);                 if ('\n'==c || EOF==c) break;//             }         }         while (1) {//去掉行尾的'\n'和空格             if ('\n'==ln[L] || ' '==ln[L]) {                 ln[L]=0;                 L--;                 if (L<0) break;//             } else break;//         }         if (L>=0) {             if (ignore_case) {                 if (NULL==bsearch(ln,buf,n,MAXCHARS,icompare)) printf("%s\n",ln);             } else {                 if (NULL==bsearch(ln,buf,n,MAXCHARS,compare)) printf("%s\n",ln);             }         }     }     fclose(fp);     free(buf);     return 0; }


Question: ubuntu进程调用子进程执行不同的任务

谢谢了哈，我仔细学习一下

《Unix编程艺术》

我就想要一个例子  大哥们速度给一个呀

//#include "apue.h"  #include <unistd.h> #include <stdlib.h> #include <stdio.h>  #define err_sys(str) perror(str), exit(-1)  int		globvar = 6;		/* external variable in initialized data */ char	buf[] = "a write to stdout\n";  int main(void) { 	int		var;		/* automatic variable on the stack */ 	pid_t	pid;  	var = 88; 	if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1) 		err_sys("write error"); 	printf("before fork\n");	/* we don't flush stdout */  	if ((pid = fork()) < 0) { 		err_sys("fork error"); 	} else if (pid == 0) {		/* child */ 		globvar++;				/* modify variables */ 		var++; 	} else { 		sleep(2);				/* parent */ 	}  	printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, 	  var); 	exit(0); }

看《UNIX环境高级编程》《网络编程第2卷》上面例子很多，有其后面一本

楼主要的是进程池？

你要学的东西好多， 进程间通信， fork和vfork函数的区别。 还有让子进程运行不同的任务， 需要研究exec 函数族。。

在网上搜demo


Question: printf("123"); 	while(1); 在Linux下无输出，在Windos下有输出？

谢谢各位的回答~fflush()很好用~

1l， 2l的方法都可行。 printf输出到屏幕的几种情况： 1.输出缓冲区满了 2. 程序结束 3. 遇到"\n" (1L的办法) 4. 人为刷新输出缓冲区.(2楼的办法，fflush(stdout));

用fflush(stdout)

加一个换行 "123\n" 试试


Question: 一个似乎是C++可以解决的问题

跟 c++ 没必然联系，就是写模拟程序，先写清楚算法，再按照算法写实现，哪里卡住了再说具体问题。

这不是《概率统计》书里面的习题吗？你查查浙大那一本，温习下知识，自己就能搞定

这东西首先是个数学问题, 我不知道算的对不对.渣数学 for 1-1000   分别计算R1R2R3是否坏了(如R1坏几率是58%, 取随机数(1-100), 如果随机数在1-58之间, 就是坏了)   if(需要修理)     修理     t修理时间增加(修理时间也就是停运时间, 可以按R1R2R3分别计算)   else     t正常时间增加 print t正常时间, t修理时间 tr1 tr2 tr3(修理r1r2r3的时间)

不用考虑A,B都坏了，C就不用工作这种情况，认为三个是完全独立的。


Question: EPOLL 的 TCP 服务端程序，遇到两个问题，请做过EPOLL的帮解释一下

每次，接受的数据都在变，为啥端口没有变呢？


Question: C语言，注册用户名的问题 大神求教呀

仅供参考：//文件1中的内容排序并去重,结果保存到文件2中 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXCHARS 128      //能处理的最大行宽,包括行尾的\n和字符串尾的\0 int MAXLINES=10000,MAXLINES2; char *buf,*buf2; int c,n,hh,i,L; FILE *f; char ln[MAXCHARS]; int ignore_case=0; int icompare(const void *arg1,const void *arg2) {    return stricmp((char *)arg1,(char *)arg2); } int compare(const void *arg1,const void *arg2) {    return strcmp((char *)arg1,(char *)arg2); } int main(int argc,char **argv) {     if (argc<3) {         printf("Unique line. Designed by zhao4zhong1@163.com. 2012-08-20\n");         printf("Usage: %s src.txt uniqued.txt [-i]\n",argv[0]);         return 1;     }     if (argc>3) ignore_case=1;//若存在命令行参数3，忽略大小写     f=fopen(argv[1],"r");     if (NULL==f) {         printf("Can not find file %s!\n",argv[1]);         return 1;     }     buf=(char *)malloc(MAXLINES*MAXCHARS);     if (NULL==buf) {         fclose(f);         printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES,MAXCHARS);         return 2;     }     n=0;     hh=0;     i=0;     while (1) {         if (NULL==fgets(ln,MAXCHARS,f)) break;//         hh++;         L=strlen(ln)-1;         if ('\n'!=ln[L]) {//超长行忽略后面内容             printf("%s Line %d too long(>%d),spilth ignored.\n",argv[1],hh,MAXCHARS);             while (1) {                 c=fgetc(f);                 if ('\n'==c || EOF==c) break;//             }         }         while (1) {//去掉行尾的'\n'和空格             if ('\n'==ln[L] || ' '==ln[L]) {                 ln[L]=0;                 L--;                 if (L<0) break;//             } else break;//         }         if (L>=0) {             strcpy(buf+i,ln);i+=MAXCHARS;             n++;             if (n>=MAXLINES) {                 MAXLINES2=MAXLINES*2;                 if (MAXLINES2==1280000) MAXLINES2=2500000;                 buf2=(char *)realloc(buf,MAXLINES2*MAXCHARS);                 if (NULL==buf2) {                     printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES2,MAXCHARS);                     printf("WARNING: Lines >%d ignored.\n",MAXLINES);                     break;//                 }                 buf=buf2;                 MAXLINES=MAXLINES2;             }         }     }     fclose(f);     if (n>1) {         if (ignore_case) qsort(buf,n,MAXCHARS,icompare);         else qsort(buf,n,MAXCHARS,compare);     }     f=fopen(argv[2],"w");     if (NULL==f) {         free(buf);         printf("Can not create file %s!\n",argv[2]);         return 2;     }     fprintf(f,"%s\n",buf);     if (n>1) {         if (ignore_case) {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if (stricmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         } else {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if ( strcmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         }     }     fclose(f);     free(buf);     return 0; }


Question: 读取指定个数的字符，按照要求输出。当指定数目≥32时，出错。

引用 3 楼 jiht594 的回复:int number;       if(argc > 1){         printf("Please enter the maximum number you want input: ");         scanf("%d", &number);         char *string = new char[number]; ... ...        delete[] string; 我知道了，在声明变长数组之前，变量必须先被赋值。

1楼把你的问题指出来了， 你的 char strings[number]  要动态分配。。你不管传多少，你的字符数组strings的大小在程序启动的时候就已经定死了。

数组大小不能动态变化。

需要修改： char string[100];

没发现你所说的问题。

/***********************************************************************  *读取输入直到文件结尾，按照用户指定输出  *-p：原样输出；-u：转为大写；-l转为小写  * */ #include <stdio.h> #include <ctype.h>  void getInput(char *string, int number); void toUpper(char *string); void toLower(char *string); void showString(const char *string);  int main(int argc, char *argv[]) {     int number;     char *string;      if(argc > 1){         while (1)             printf("Please enter the maximum number you want input(1..10000000): ");             fflush(stdout);             rewind(stdin);             number=0;             scanf("%d", &number);             if (1<=number && number<=10000000) break;         }         string=new char[number];         if (NULL==string) return 1;         while('\n' != getchar())             ;         getInput(string, number);         switch(argv[1][1]){             case 'p': printf("You choose SHOW IT SELF: \n");                       showString(string);                       break;             case 'u': printf("You choose TOUPPER: \n");                       toUpper(string);                       showString(string);                       break;             case 'l': printf("You choose TOLOWER: \n");                       toLower(string);                       showString(string);                       break;             default : printf("WRONG!\n");         }         delete[] string;     } else         printf("Please enter \"-p\" or \"-l\" or \"-u\" atfer the "                 "program name!\nDone!\n");      return 0; }  void getInput(char *string, int number) {     int index;      printf("Please enter no more than %d characters:\n", number);     for(index=0; index<number; index++)         string[index] = getchar();     string[index] = '\0'; }  void toUpper(char *string) {     while(*string){         *string = toupper(*string);         string++;     } }  void toLower(char *string) {     while(*string){         *string = tolower(*string);         string++;     } }  void showString(const char *string) {     while(*string)         putchar(*string++); }


Question: 求大神指点迷津，创建单链表！

仅供参考：//带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*s1,*s2,*s3,*s4,*s; int i,j,k,n,t,m; int main() {     srand(time(NULL));      //填写头节点数据     H.data=-1;     H.next=NULL;     head=&H;      //创建10个节点的单链表     p=head;     for (i=0;i<10;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) return 1;         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         p->next=q;         p=q;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将值为5的结点插入到单链表的第k个结点前     k=3;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) return 1;             q->data=5;             q->next=p->next;             p->next=q;             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //删除第k个节点     k=5;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=p->next;             if (q) {                 p->next=q->next;                 free(q);             }             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //从小到大排序     for (p=head;p!=NULL && p->next!=NULL;p=p->next) {         for (q=p->next;q!=NULL && q->next!=NULL;q=q->next) {             if (p->next->data > q->next->data) {                  //交换data //              printf("swap %02d %02d\n",p->next->data,q->next->data); //              t=p->next->data;p->next->data=q->next->data;q->next->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->next->data,q->next->data);                 s1=p->next;                 s2=p->next->next;                 s3=q->next;                 s4=q->next->next;                  if (s2!=s3) {                      p->next=s3;                     s3->next=s2;                      q->next=s1;                     s1->next=s4;                 } else {                      p->next=s3;                     s3->next=s1;                            q=s3;                     s1->next=s4;                 }                  //输出整个单链表 //              s=head->next; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将单链表中前 m 个结点和后 n 个结点进行互换,m+n为链表总长10     m=4;     n=6;     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m+1==k) {             q=p;         }         s=p;         p=p->next;     }     s1=head->next;     head->next=q->next;     s->next=s1;     q->next=NULL;      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head->next;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //18->94->58->17->27->20->43->57->75->78-> //18->94->05->58->17->27->20->43->57->75->78-> //18->94->05->58->27->20->43->57->75->78-> //05->18->20->27->43->57->58->75->78->94-> //43->57->58->75->78->94->05->18->20->27-> //

OrZ      谢谢！

引用 2 楼 NotSimpleEasy 的回复:可否能把我的代码改一下！再次表示感谢！ 闲着也是闲着！ #include <stdio.h> #include <stdlib.h> #include <malloc.h> struct node {     int data;     struct node *next; }; struct node *creat(struct node*); void Output(struct node*); void destroy(struct node*); int main() {     struct node*head;     head=NULL;     head=creat(head);     Output(head);     return 0; } struct node *creat(struct node *head) {     int i,LEN;     struct node*p,*s;      printf("请输入链表长度LEN：");     fflush(stdout);     scanf("%d",&LEN);     if (LEN<1) return NULL;     p=(struct node *)malloc(sizeof(struct node));     printf("p=%p\n",p);     printf("请输入结点中的数据：");     fflush(stdout);     scanf("%d",&p->data);     p->next=NULL;     head=p;     for(i=0;i<LEN-1;i++) {         s=p;         p=(struct node *)malloc(sizeof(struct node) );         printf("请输入结点中的数据：");         fflush(stdout);         scanf("%d",&p->data);         p->next=NULL;         s->next=p;     }     return(head);  } void Output(struct node*head) {     struct node*temp;     temp=head;     while (1) {         if(temp!=NULL) {             printf("%d->",temp->data);             temp=temp->next;         } else break;     }     printf("\n"); } void destroy(struct node*head) {     struct node*temp,*p;     temp=head;     while (1) {         if(temp!=NULL) {             p=temp->next;             free(temp);             temp=p;         } else break;     } } //C:\>test //请输入链表长度LEN：0 // // //C:\>test //请输入链表长度LEN：1 //p=004218C0 //请输入结点中的数据：1 //1-> // //C:\>test //请输入链表长度LEN：2 //p=004218C0 //请输入结点中的数据：1 //请输入结点中的数据：2 //1->2-> // //C:\>test //请输入链表长度LEN：3 //p=004218C0 //请输入结点中的数据：1 //请输入结点中的数据：2 //请输入结点中的数据：3 //1->2->3-> // //C:\>

可否能把我的代码改一下！再次表示感谢！


Question: ubuntu下读出的中文标点无法匹配

谢谢三楼！！

我觉得无论用什么编码方式存储的（实际是utf-8），读出来总可以通过str[i]&0xff  ==  ？str[i+1]&0xff == ？,str[i+2]&0xff == ？进行匹配吧？

ubuntu环境一般是UTF-8编码吧。。所以'，'占三个字节，你要比较三个字节才行 你试试 char str[] = "，"; printf("%d", sizeof(str)); 应该是4吧

。和，不是一回事！

你把关键代码贴出来看看


Question: 遗传算法给染色体解码程序中 if(*pointer-'0') 这句是什么意思？

引用 1 楼 zhao4zhong1 的回复:等价于 if(pointer[0]-'0'!=0) 即pointer[0]不是'0'  大哥能解释下这个函数吗   我不太懂  为什么是 if(*pointer-'0') {decimal+=(long)pow(2,i);} 谢谢

引用 2 楼 jp417799578 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 等价于 if(pointer[0]-'0'!=0) 即pointer[0]不是'0'  大哥能解释下这个函数吗   我不太懂  为什么是 if(*pointer-'0') {decimal+=(long)pow(2,i);} 谢谢[/quote] 如果当前位置的字符不是'0'（那也就是'1'了），将当前二进制字符串对应的十进制数decimal累加2的i次方。

这一句相当于比较pointer[0]的字符和‘a’字符相不相等的意思。是通过ascii来比较的，字符相同的ascii值就是一样的。


Question: 大二菜鸟求助

整整一年，我终于弄明白了  谢谢大家

动态分配内存       （首地址类型）malloc（每块内存大小*内存块数）     一般将他的返回值赋给一个指针！其他的看书吧！

#include<stdio.h> #include<stdlib.h>  struct person { 	char name [10]; 	int age; 	char sex [10]; 	struct person *next; };  struct person *per = (struct person*) malloc (20 * sizeof (struct person) );  int main (int argc, char** argv) {   struct person person1 = {"person",18,"sex"};    printf("%s\t%ld\t%s\t",person1.name,person1.age,person1.sex);   return 0; }  首先结构体中定义的 name 只是一个字节，是存不了两个汉字的长度的，sex 也一样道理。 再者，全局变量可以在声明时初始化，但不能像你写的那样重新用一个赋值语句，如果要这样写，就在函数上下文中写，即是在main （）中写。

#include<stdio.h> #include<stdlib.h> struct person { char name[10]; int age; char sex[3]; struct person *next; }; //struct person *per; //per=(struct person*)malloc(20*sizeof(struct person));  void main() { struct person *per; per=(struct person*)malloc(20*sizeof(struct person));  struct person person1={"人物",18,"男"};  printf("%s\t%ld\t%s\t",person1.name,person1.age,person1.sex); } 你的结构体创建要注意一些问题，汉字是一个字、俩字节。动态创建有好处就是你需要多少结点就建立多少结点，给你省很多空间。

3楼定义全局变量不能调用函数。  要么将struct person *per = (struct person*) malloc (20 * sizeof (struct person) );这句置于main函数中。  或者定义全局变量struct person *per；空间分配在main函数内per= (struct person*) malloc (20 * sizeof (struct person) )。

你需要好好去看书,  或者去贿赂一下学的好的同学, 然后请教他(她)


Question: c语言问题

int i = 0; int sum = 0; char state[30];  // initialize state array... for (; i < 30; i ++) {     sum += state [i] ? state [i] : 0; } // output sum   代码应该是这样

创建一个30单位的char 数组，每一个元素代表一天的出勤情况，1代表出勤，0代表缺勤。 之后迭代这个数组，如果元素为1，则工资总和加上50，否则continue。 很简单的问题！  int i = 0; int sum = 0; char state[30];  // initialize ... for (; i < 30; i ++) {     sum += state [i] ? state : 0; } // output sum

仅供参考 #include <stdio.h> #include <stdlib.h> void main() { 	char state[31]={0}; 	for(int i=0;i<31;++i) 	{ 		state[i]=rand()%2; 	} 	int salary=0; 	for(int j=0;j<31;++j) 	{ 		salary+=state[j]*50; 	} 	printf("三月份工资为:%d\n",salary); }

如果不用程序你会做吗，很难............


Question: 一个很操蛋的问题

VS IDE中，在不明白的符号上点鼠标右键，选转到定义。

你这，，，，，，，，，，

顶下，领分哦。。

VC中errno是一个宏吗，我以为只是在Linux/Unix中的系统才是定义过的...


Question: 求大神创建一个单链表

我也是初学者，自己写了个，不过是c++的有兴趣可以看看，希望能帮到你。 http://blog.csdn.net/zuiailongkui_yanghl/article/details/44804707

关注，学习，这个“判断指针域是否为NULL来终止创建的方式”怎么做？


Question: 把英文小写字符串转化成整形数组，就是把a~z变成0~25，但a在转换的时候会发生错误，直接跳过了，请问怎么回事？

谢谢指导，是我自己大意了

while(s2[j]) 既然你把a转化为0，那么还用0来判断不就是说把a视为不存在了吗？ 用 while(j < i) 吧

输入什么，输出什么，什么错误总要说清楚

‘a’-96=1，所以你转换的结果对应的是1-26，而不是0-25。  因此按要求应该s1[i]-97。  此外，输出的循环的条件按楼上修改。

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。


Question: 小弟又来啦  fread的问题！！！大神

局部变量自己先初始化一下,char b[7]={0};

fread(b,2,3,fp);    MSDN上从来没有说过fread会自动加\0

没有0，多加个0就可以了

应该而实际没做到的事多了去了！

为什么要自动加0 请你告诉我，你是从哪里看到的，请告诉我好吗？我很好奇，真的想知道。 菜鸟等你的回答。

局部变量注意要初始化！ b[7]={0};就不会出现?问题了

2*3 = 6 自己赋个'\0'吧


Question: 初学菜鸟求各位大神帮助

多谢楼上各位，当时手机上传的图片，没想到没有上传成功。发完贴后没有上，没想到由楼上几位大咖回复，小弟再次谢过，以后常问！

请问图在哪里？耐心上传，我们为你解答

图呢……无语

搞了半天到底想问什么啊？

慢慢总结经验，先自己寻求解决方案！别人帮你解决的也只是别人的经验，还需要自己努力才行啊！

2楼没图也能回答问题并且得分。

就是没图才来问，有图还问你们干什么！真是的。 东晋·僧肇（384～414），善《老》《庄》，后读《维摩经》，写成一书，取名《肇论》，共一卷，计五篇。其中，《不真空论》说道：虽无而有，虽有而无，非有非无，称之为“空”。

没图呀 ~~~~~

引用 楼主 u013409439 的回复:各位大神，初学c语言菜鸟求助 图中第六题的结果我看不懂，求解答   图在哪里？


Question: 识别标识符

参考TCC源代码。


Question: nrf905发送多个数据问题

求解了。不胜感激的。


Question: 紧急！帮忙把这个matlab代码转成C代码吧

引用 4 楼 LongxiaoZeng2001 的回复:针对楼主问题，2个解决方式： 1.优化你的m文件，能否借助使用矩阵，matlab的向量化计算提高速度；在matlab中能不使用for就绝不使用，会拖慢速度(使用向量化方式)； 2.使用其他语言实现算法，而不是转化代码，推荐python+numpy，plot使用matplotlib；当然针对你问题，fortran之类的最好；   赵老师：不赞成你的“也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。”，这是混编吧？matlab就是这么干的，小的不才，最近准备混编c+fortran。 你还可以在你今后的苦海畅游生涯中混编： C Java Objective-C C++ C# PHP JavaScript Python Visual Basic .NET Visual Basic F# Perl Delphi/Object Pascal Transact-SQL Pascal ABAP PL/SQL Ruby MATLAB R SAS Logo Swift COBOL ML PostScript OpenEdge ABL Assembly Fortran ActionScript D Lisp Scratch Ada Scala Groovy Lua C shell Prolog Max/MSP Scheme RPG (OS/400) Awk PL/I Inform VBScript Go Z shell (Visual) FoxPro LabVIEW

你要plot这就比较麻烦了。。

不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件，或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如： A将请求数据写到文件a.txt，写完后改名为aa.txt B发现aa.txt存在时，读取其内容，调用相应功能，将结果写到文件b.txt，写完后删除aa.txt，改名为bb.txt A发现bb.txt存在时，读取其内容，读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境，B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢？  共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多，下面仅列出我现在能想到的： ·进程之间松耦合 ·进程可在同一台机器上，也可跨机，跨操作系统，跨硬件平台，甚至跨国。 ·方便调试和监视，只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务，只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务，而且几乎不可能发生队列满的情况（除非硬盘空间满） ·……  “跨语言、跨机，跨操作系统，跨硬件平台，跨国，跨*.*的”苦海无边， 回头是“使用共享纯文本文件进行信息交流”的岸！

不会用vs就换txt，txt都不会用就没法了。


Question: 求问个算法问题

我的思路跟楼上一样，变成多个等差数列来算，下面的除法(/)都是整数除法： n%1=n-(n/1)*1 n%2=n-(n/2)*2 n%3=n-(n/3)*3 ... n%n=n-(n/n)*n sum{n%n}=n*(n-1)-((n/2)*2+(n/3)*3+...+(n/n)*n) 设n/2=a，那么n/(a+1)==1,n/(a+2)==1,...,n/n==1，所以(n/(a+1))*(a+1)+...+(n/n)*n==(a+1)+(a+2)+...+n 设n/3=b，那么n/(b+1)==2,n/(b+2)==2,...,n/a==2，所以(n/(b+1))*(b+1)+...+(n/a)*a==2*((b+1)+(b+2)+...+a) ... 算到n/x<=2为止，这样算出来了。 这样算要考虑的是整型越界问题，呵呵，能用int64的话就无所谓，不能用就弄个大整数四则运算函数

设n=s*q+r,s>r,s<=q,则n%s=n%q=r,s<=√n 举个例子，n为17 s  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 r   0  1  2  1  2  5  3  1  8  7   6   5   4   3    2    1    0 除数s从17到9,余数r为从0到8,公差为1的等差数列.s:17对应1. 除数s从8到6,余数r为从1到5,公差为2的等差数列.s:8对应2 再往前，s:5与3对应，剩个4  下面先证明一下等差数列： 设1<=t<=√n,u=n/t,则s为t与u时余数相同，设为r 则n-r=t*u 设除数为u-1时商也为t,n-r-x=t*(u-1) 则x=t. 同理，除数为u-k时，x=kt. 所以，除数大于√n时，会形成多个等差数列.  下面求一下k的范围： 设被除数为n,商为t(t<=√n) 因为除数大于余数,余数为r+kt=n%t+t*k 则(n-(n%t+t*k))/t>n%t+t*k. 解得:k<(n/t-n%t)/(t+1) 则k最大取(n/t-n%t-1)/(t+1),设为K 所以从右到左第t个等差数列为:从n%t到n%t+t*K,公差为t,共K+1项.和为t*K/2+n%t. 1<=t<=√n 再把每个等差数列的和加起来，其结果就是n%(n/√n)+...+n/n 这一步时间复杂度为O(√n)  再把n%1+...+n%√n加上 因为√n<=n/√n,当等于的时候,n%√n加了两次,这时需要减一下n%√n 这一步时间复杂度也为O(√n) 最后，两步的和即为n%1+n%2+...+n%n,然后再取个余就行了。  说了这么多，代码你就自己写吧。

这题限时是1sec 不能暴力

引用 2 楼 user-3 的回复:定一个数k，x<=k的时候n%k暴力算，x>k的时候对于所有y<=n/k，每一个y用O(1)时间算出所有n/x=y的n%x的和。这样总共是O(k)+O(n/k)复杂度，k取sqrt(n)的时候达到最优。 能细说下你这个算法的原理吗 我还不是很懂


Question: 如何使用powergui模块FFT分析实际采集的电压信号的谐波。

百度搜相关关键字。

我也用FFT分析谐波，能把程序发给我吗


Question: 动态库 疑问

感觉这应该是操作系统的活，我们只要做好动态链接就行了。

《深入解析Windows操作系统-Windows Internals》

PE装载器会对这些进行处理，如果依赖的dll 已经在内存中了，则将调用例程的地址映射到PE 的IAT 中，这部分对用户是透明的，建议查查装载器相关的资料。 如果进程B 退出了，如果没有使用A 库，则这部分会被装载器回收掉！

补充，进程B退出的时候，如果没有进程使用库A，A是继续驻留内存呢还是退出内存

为了提高查找和加载动态连接库的效率，系统启动后会通过ldconfig工具创建一个库的缓存/etc/ld.so.cache。链接器要从LD_LIBRARY_PATH指定的路径中找到相关的库文件或者直接从/etc/ld.so.cache库缓冲中加载相关库到内存中。

这部分工作有链接器负责。


这个是规定 记住就行了 做程序员还是需要点记忆能力的

引用 2 楼 vnvlyp 的回复:SET就是set，设置的意思 man里就有说明 SEEK_SET               The offset is set to offset bytes. SEEK_CUR               The offset is set to its current location plus offset bytes. SEEK_END               The offset is set to the size of the file plus offset bytes. SEEK_SET就是设置到offset位置 SEEK_CUR是设置到offset位置加上当前位置 SEEK_END是设置到offset位置加上文件大小  说的有道理，谢谢~~~

这么说SEEK_SET 中的SET是offset的缩写？  为何不用SEEK_BEGIN这样的名字？

个人感觉SET表示分两步，一：把文件指针设置到文件头（所有用SET），二，从文件开头处偏移。


Question: 疑惑，你清楚吗？

Sorry，没有看清运行的结果~~~

电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。

不要使用 while (条件) 更不要使用 while (组合条件) 要使用 while (1) {  if (条件1) break;  //...  if (条件2) continue;  //...  if (条件3) return;  //... } 因为前两种写法在语言表达意思的层面上有二义性，只有第三种才忠实反映了程序流的实际情况。 典型如： 下面两段的语义都是当文件未结束时读字符 while (!feof(f)) {  a=fgetc(f);  //...  b=fgetc(f);//可能此时已经feof了！  //... } 而这样写就没有问题： while (1) {  a=fgetc(f);  if (feof(f)) break;  //...  b=fgetc(f);  if (feof(f)) break;  //... } 类似的例子还可以举很多。

引用 3 楼 imfang 的回复:注意下面两行的区别： (*9,16)000000008请按任意键继续. . . (*9,0)000000008请按任意键继续. . .  都是在读取到9个字符后并正好到文件未，为何显示的值不一样！  2楼说的很清楚，第二个程序恰恰是因为程序并不知道读到了文件末尾。只是你认为到了末尾。

引用 1 楼 user-6 的回复:feof返回 非0值, 表示EOF  第二段程序, 你在while(){} 后面再输出一下feof(f)试一下  feof在文件指针指完EOF后才返回非0值

(*9,0)000000000(*9,0)000000008(*9,16)000000008请按任意键继续. . . (*9,0)000000000(*9,0)000000008请按任意键继续. . .

仔细看feof的文档是怎么说的： Checks whether the end-of-File indicator associated with stream is set, returning a value different from zero if it is. This indicator is generally set by a previous operation on the stream that attempted to read at or past the end-of-file. Notice that stream's internal position indicator may point to the end-of-file for the next operation, but still, the end-of-file indicator may not be set until an operation attempts to read at that point. feof只是检查这个流的EOF标识，EOF标识一般只由之前的操作设置，比如fgetc fgets之类的，你第二个程序最后一个fgets正好读取到了文件末尾，但是这时候EOF标识是没有设置的，因为流并不知道文件读到末尾了，你必须再读一次发生错误流才知道文件读完了。你可以试试就算一个空文件，你feof肯定是0，因为你都没有进行任何操作流完全不知道这是个空文件。


Question: linux中如何输入 EOF ？

谢谢。  最终实现是 ctrl+d ctrl+d  按两次  第一次的ctrl+d相当于\n 第二次才是EOF

按Ctrl-Z是将该程序转为后台运行。要输入fg将该程序转到前台。 输入Ctrl-D应该是EOF


Question: 求助Win32 API的串口的数据读取，代码如下

特供调试时使用：void HexDump(char *buf,int len,int addr) {     int i,j,k;     char binstr[80];      for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%08x -",i+addr);             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         } else if (15==(i%16)) {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);             sprintf(binstr,"%s  ",binstr);             for (j=i-15;j<=i;j++) {                 sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');             }             printf("%s\n",binstr);         } else {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         }     }     if (0!=(i%16)) {         k=16-(i%16);         for (j=0;j<k;j++) {             sprintf(binstr,"%s   ",binstr);         }         sprintf(binstr,"%s  ",binstr);         k=16-k;         for (j=i-k;j<i;j++) {             sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');         }         printf("%s\n",binstr);     } }

恩这是个问题，还有我发现在打印buffread时只有前两个字节是能显示的，后面的就打印不出来，估计是buffread本身被写入时就有问题。也不是很清楚这个写入的机制？

ReadFile的第三个参数,你用的变量nwrite得赋个初值吧,貌似全局变量会自动赋初值为0,大概?


Question: 简易的printf函数

先 http://www.microsoft.com/visualstudio/chs/downloads#d-2010-express 点开Visual C++ 2010 Express下面的语言选‘简体中文’，再点立即安装  再参考 C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\output.c

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）

引用 2 楼 guicaisa 的回复:[quote=引用 1 楼 user-3 的回复:] f = (float)va_arg(ap, double);  我擦，，神了，，求告知原理，，，是我初始化的值选的不好吗。。。[/quote] 自动类型提升，float会提升成double，就像char和short也会提升成int一样

引用 2 楼 guicaisa 的回复:[quote=引用 1 楼 user-3 的回复:] f = (float)va_arg(ap, double);  我擦，，神了，，求告知原理，，，是我初始化的值选的不好吗。。。[/quote]  好象是va_arg 不支持float, 需要用double代替

引用 1 楼 user-3 的回复:f = (float)va_arg(ap, double);  我擦，，神了，，求告知原理，，，是我初始化的值选的不好吗。。。

f = (float)va_arg(ap, double);


Question: 杭电1005，runtime error,提示stack overflow,帮忙看下。。。

引用 6 楼 Falleyes 的回复:这种题使用递归不光是栈溢出，还很可能超时。这是道数字题，看看下面的AC代码吧~#include<iostream> using namespace std; int main() { 	int A,B; 	unsigned int n; 	cin>>A>>B>>n; 	while(A&&B&&n) 	{ 		int *p=new int[50];    //存在循环，在这里判断，来减少运行时间 		if(n>50) 			n=(n-2)%48+2; 		*p=*(p+1)=1; 		for(int i=2;i<n;i++) 			*(p+i)=(A**(p+i-1)+B**(p+i-2))%7;  //公式 		cout<<*(p+n-1)<<endl; 		cin>>A>>B>>n; 	} 	return 0; } 6楼正解，直接循环n次的即使不stack overflow，也会超时，因为析好像是最只有50个结果就会出现循环，具体怎么分析的我就不清楚。另外一种比较容易理解的就是构造一个矩阵，使用矩阵快速幂。

这题不需要递归，已经知道f(n-1),f(n-2) 得到f(n) 既然从f(1),f(2) 就得到f(3) ,同时f(1)就没有用了，用int f[2] 来计算一下就可以了    int f[2];     f[0] =f[1] =1;     int cur=1,last=0;     for(int i=0;i<n;i++)     {         cur ^=1,last ^=1;         f[cur]  =(A*f[last] + B *f[cur]) %7;     }

引用 4 楼 user-4 的回复:引用 3 楼 Miss_Play 的回复:[quote=引用 2 楼 user-4 的回复:] 递归深度太深了.不是用递归做吗QAQ太深会怎样，devC运行正确啊。。。 栈会用光的  你试过 999 999 999999999吗  我其实没看题.....反正递归太深是不行的. [/quote]我先去查查stack是什么。。。

引用 3 楼 Miss_Play 的回复:引用 2 楼 user-4 的回复:递归深度太深了.不是用递归做吗QAQ太深会怎样，devC运行正确啊。。。 栈会用光的  你试过 999 999 999999999吗  我其实没看题.....反正递归太深是不行的.

递归深度太深了.

【附题】  Problem Description A number sequence is defined as follows:  f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.  Given A, B, and n, you are to calculate the value of f(n).    Input The input consists of multiple test cases. Each test case contains 3 integers A, B and n on a single line (1 <= A, B <= 1000, 1 <= n <= 100,000,000). Three zeros signal the end of input and this test case is not to be processed.    Output For each test case, print the value of f(n) on a single line.    Sample Input 1 1 3 1 2 10 0 0 0    Sample Output 2 5


Question: 请大神运行一下，然后解释下哪里出错了？我要详细回答，谢谢，详细告诉我原因

这个代码根本不能编译通过。  move方法的少了一个 右大括号 }  其它问题：   {int *q,t,i,j; int *min,*max; min=max=p; for(i=0;i<5;i++)   // for语句的循环体应该使用 {} 明确的表示出了。 for(j=0;j<5;j++) if(*min>*(p+5*i+j))min=(p+5*i+j);  // if 语句的从句，不要与if写在一行上，应该换行。 else if(*max<*(p+5*i+j))max=(p+5*i+j);

要学着自己单步一个. 还有,上代码时格式化下,...要不然难看死啦,还有.说明一下代码的意图...   void move(int *p)  {    ///////.............     min=p+1;     for(i=0;i<5;i++)         for(j=0;i<5;j++)    /// 这里死循环了:这个 i<5 ,.... 应该是  j<5 吧 .         {             if((i==0&&j==0)||(i==0&&j==4)||(i==4&&j==0))continue;             if(*min>*(p+5*i+j))min=(p+5*i+j);         }        t=*min;    //// .......


Question: 请问在vs2013中，这句代码显示不是很清楚，这表示什么意思？

VS IDE中，在不明白的符号上点鼠标右键，选转到定义。

引用 4 楼 bo2256321 的回复:其中_WIN32和_stdcall表示什么？谢谢 这种名词解释问题直接google，MSDN

引用 2 楼 60 的回复: 这叫“非活动代码”，由于没有定义宏“CUFFTAPI”，ifndef的结果为真，#else中的这些代码不会被编译。 谢谢，能否顺便解释下#ifdef _WIN32 #define CUFFTAPI _stdcall 其中_WIN32和_stdcall表示什么？谢谢

导出函数的宏定义，在windows下使用__stdcall，在linux下使用默认的cdecl

条件宏中不满足条件的代码


Question: 想到一个问题：如何用逻辑或数学运算取代IF判断。

if(A%B==0) return 1 else return 0  ===========  float C = A%B; return 1^(   (int)( C/(C+0.01f) + 0.5f )  )  ;

嘿嘿，楼主能把CMP指令从cpu里扒掉吗

IF不能取代吧，试想如果汇编不能用IF，相当于只能使用JMP和CALL指令来跳转，并且所有的比较指令都不能用，你说程序怎么写？

引用 2 楼 u012677852 的回复:[quote=引用 1 楼 user-4 的回复:] 条件判断是不可替代的  数学上证明过  求最大值不就可以么？？[/quote]  假如，你用很巧妙的方法用异或实现了if（我个人目前认为可行） 但异或本身就是在判断啊  所以我觉得没什么意义

引用 1 楼 user-4 的回复:条件判断是不可替代的  数学上证明过  求最大值不就可以么？？

条件判断是不可替代的  数学上证明过


Question: 读取串口数据请教

串口的数据比较易丢帧粘帧, 读写的频率最好不要快过 帧/15ms.,(即收发数据的轮询次数).

不台了解详情，猜的：感觉是读了一次后，才真正触发，把数据读到缓冲区，第一次只是中断到，并没有把数据放到缓冲区。


Question: 如何建立参数初始化

五个变量为g_wSYZJ，g_wSYAA，g_wSYAB，g_wSYAC，g_wSYAD  变量cwPASSIVE_CNT=5

这个估计没人能帮你。  1）首先不知道要初始化哪5个变量 2）其次没人知道你的EEPROM是怎么连接的，只有硬件文档或者硬件设计者知道，你要查文档或者问硬件开发者。 3）没人知道你需要的5个变量是干什么的，只有把内部实现全理解了或者接口说明理解了，才知道怎么填这些变量。

是建立5个变量

建立5个函数，如何初始化


Question: vs2013生成可执行程序的问题

如果你使用VS创建了项目，可以修改项目的“生成配置”，直接在工具栏上修改，修改为Win32 或者 修改“生成”-“配置管理器”，新建一个配置，使用Win32 。

引用 2 楼 liguanpei 的回复:[quote=引用 1 楼 user-2 的回复:] ""C:\Program Files\Microsoft Visual Studio 11.0\VC\vcvarsall.bat"" x86 直接修改为goto x86 么？还有保存的时候说在别的程序中打开，不能修改[/quote]  在控制台输入上面的命令就好了，你的开始菜单应该已经有这个链接了。

引用 1 楼 user-2 的回复:""C:\Program Files\Microsoft Visual Studio 11.0\VC\vcvarsall.bat"" x86 直接修改为goto x86 么？还有保存的时候说在别的程序中打开，不能修改


Question: sed命令修改一个变量，让变量的内容变为大写。

\l   Turn the next character to lowercase,   这种事情自己查手册吧。


谢谢谢谢谢谢1

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。

你看下你的for循环怎么写的。  能这样么？ for() {        for()        {         } }

%d能把double正确打印出来吗？ 看你这段代码，去掉最高最低分求平均吧，写的好啰嗦，一次循环就够了啊


Question: 求助关于强制类型转换的问题

引用 2 楼 Afdadfssff 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] VC编译选项加/EP /P，重新编译，查看宏展开后对应的.i文件。gcc加-E 如何进VC编译选项呢？最好能给个图[/quote] 离不开看图识字的人是在卖萌！ VC6：   VS20XX：

先转WORD就是扔掉 超过16位的部分,转成DWORD之后就可以转成LPSTR了

引用 1 楼 zhao4zhong1 的回复:VC编译选项加/EP /P，重新编译，查看宏展开后对应的.i文件。gcc加-E 如何进VC编译选项呢？最好能给个图

VC编译选项加/EP /P，重新编译，查看宏展开后对应的.i文件。gcc加-E


Question: C语言编程题，谁会？

http://www.cnblogs.com/emituofo/archive/2012/11/14/2770193.html 这里有答案

例如：15=1+2+3+4+5       15=4+5+6       15=7+8       所以结果有3组值分别是1->5, 4->6, 7->8


Question: 新手写的堆排序，求教下maxheapcreat那里为什么老报错

谢谢ls

int temp=a[i],j=2*i+1;

偶遇到类似问题都是用 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。

E:\Sort\MaxHeapSort\MaxHeapSort.cpp(12) : error C2059: syntax error : 'bad suffix on number' E:\Sort\MaxHeapSort\MaxHeapSort.cpp(12) : error C2146: syntax error : missing ';' before identifier 'i' E:\Sort\MaxHeapSort\MaxHeapSort.cpp(12) : warning C4552: '+' : operator has no effect; expected operator with side-effect E:\Sort\MaxHeapSort\MaxHeapSort.cpp(21) : error C2059: syntax error : 'bad suffix on number' E:\Sort\MaxHeapSort\MaxHeapSort.cpp(21) : error C2146: syntax error : missing ';' before identifier 'i' E:\Sort\MaxHeapSort\MaxHeapSort.cpp(21) : warning C4552: '+' : operator has no effect; expected operator with side-effect 执行 cl.exe 时出错.


Question: 求大神搭救

你声明的是dScore  用的是 dScore1  学会看错误信息 告诉你了是dScore1没声明


Question: libpcap收发包

包是否正确？ 包的目的mac是否为目的机器的mac(ARP除外)？

记得是可以的啊

libpcap的先天不足。我猜。


Question: C语言如何获取文本文档内想要的数据

引用 4 楼 zhao4zhong1 的回复:作为一个C程序员，对  scanf,sscanf,fscanf  printf,sprintf,fprintf 这类函数的用法，还是要做到“拳不离手，曲不离口”的。 顶

假设你文件每行都是有规律的，如下代码可参考

试试  int x,y; fscanf(file_pointer,"%d;%d",&x,&y);

123456;1 32431242;3 假设格式固定为 x;y 每次读取一行 分隔字符串 用strtok 分别把分隔的俩个数 存入变量 读文件每次读一行用fgets()   只是为了读取第一个数字 也可以用fscanf 格式化读取   如果你用python处理就是 一次把文件全部加载进来，文本处理用脚本会更方便 用split('\n'),s = '\n'.join(a) 来处理 会很简单,但是你从另一个角度去想 如果你用c实现 python的 split 与join  那么也就解决了以从设计角度来讲 解决大多数文本处理的公共基本方法，


Question: C程序越界问题

下面是该好了的代码： #include <iostream> using namespace std;  int main()  {  //1 定义两个变量  int a = 0;   int x = 0;  //2 输出提示语 printf("请给出x = （4a+8）*5中a的值：");  //3 输入a的值 scanf_s("%d",&a);  //4 计算结果 x = (4*a+8)*5;  printf("%d",x);  return 0;  }

在不改变原有变量类型的情况下，建议将“scanf_s("%d",&a);”这句话改成“scanf_s("%hd", &a);”，这样就会将a当成short int进行处理而不是当成int，就不会有“stack corrupted”错误了。 原因是scanf_s是通过va_arg进行参数分析，没有严格的类型检查，所以参数出栈时是根据%里定义的type size，所以把short类型的a当成了int类型去处理了。

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。

变量 a  是一个 short 型 scanf("%d", &a);   // 这里会发生溢出,(这里最少需求一个 int 类型的空间)  把变量 a  b 改成 int a, b; 就OK了


Question: poj 1008 老是WA

感谢赵老师，确实，现在有点急功近利，老是静不下来，我会好好调试的，谢谢

tot%13有问题，这样取值为0-12了 应该是%13+1， 前面那个tot不要加1

“多一少一”问题占程序员常犯错误的10%以上！ 避免“多一少一”问题的方法之一是将比如<10甚至<5的数代入程序片断，搬手指头心算验证一下程序到底应该写为 x、x-1、x+1中的哪个？ <、<=、==、>、>=中的哪个？

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。


Question: C语言连连看程序

搜“连连看 C源代码”

二维数组。。

这~~~~~只有这些代码,只能猜啦.... 按着一般性实现的逻辑也不难猜,  build_map b[i][j] 二维表: ------------------ 1  |  2  |  1  |  5  | ... ------------------ 5  |  3  |  2  |  5  |... ----------------- 6  |  7  |  5  |  3 |.... ------------------ 里面的数字是资源号,如:   1:青瓜,   2:菊花....等等 (画面自行脑补一下) 数组 a[], 用于统计生成了多少 青瓜,, 菊花..等等 然后由...renderer 把 b[i][j] 渲染到窗口上..按 b[][] 二维格子.把物件画到相应的位置上

请问各位大神


Question: 超长算法表达式的解析

引用 10 楼 dingxz105090 的回复:[quote=引用 8 楼 my_live_123 的回复:] LZ是想语法解析呢，还是想得到最后结果呢？ 当然是要得到最后的结果，但是要得到结果就得解析语法先，不然这只是文本串，怎么能直接加到【int a = 】的后面呢   你这代码是YACC 还是 ANTLR 还是 TCC 啊[/quote] 放到int a=后为了正确语法分析，构成一个完整的定义和初始化语句。如果不要int，那么必须放到函数体内。C是结构化语言，函数外除了初始化赋值外，不能有表达式。一般编译器会给出"data definition has no type or storage class"警告。放到函数内，必须有个简单的函数体，因此归约量会增加不少。  没有使用工具，自己写的LR语法分析程序

引用 8 楼 my_live_123 的回复:LZ是想语法解析呢，还是想得到最后结果呢？ 当然是要得到最后的结果，但是要得到结果就得解析语法先，不然这只是文本串，怎么能直接加到【int a = 】的后面呢   你这代码是YACC 还是 ANTLR 还是 TCC 啊

LZ是想语法解析呢，还是想得到最后结果呢？

引用 6 楼 dingxz105090 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] 参考TCC 老赵你这不按常理出牌啊，你不是应该来一句“仅供参考”然后贴一大段代码的吗？  不过我这边也有点眉目了，可以做出来了[/quote] 我预言，未来某一天就算你自认为做出来了，再过不了多长时间，你还得去参考TCC。

int a = (((53078923 == 53086475) && ((53088651 == 53176715) || (53088651 == 53189771)) && (Date >= 201203) && (Date <= 201302)) || ((53078923 == 53086475) && (53088651 == 45417463051) && (Date <= 201302)) || ((53078923 == 53086475) && ((53088651 == 53226763) || (53088651 == 53144075) || (53088651 == 53205003) || (53088651 == 53170187) || (53088651 == 53117963)) && (Date >= 201109) && (Date <= 201206)) || ((53078923 == 53086475) && ((53088651 == 53161483) || (53088651 == 53272459)) && (Date >= 201203) && (Date <= 201206)));   语法归约过程   int  a  //归约的当前标识和下一个标识 type-specifier //归约栈信息，int 归约到type-specifier declaration-specifiers ////归约栈信息，type-specifier归约到declaration-specifiers a  =  //归约的当前标识和下一个标识，以下类似 declaration-specifiers direct-declarator //a->direct-declarator,以后雷同，只看栈顶归约信息即可 declaration-specifiers declarator  =  (   (  (   (  (   (  53078923   53078923  ==   declaration-specifiers declarator = ( ( ( primary-expression  declaration-specifiers declarator = ( ( ( postfix-expression  declaration-specifiers declarator = ( ( ( unary-expression  declaration-specifiers declarator = ( ( ( cast-expression  declaration-specifiers declarator = ( ( ( multiplicative-expression  declaration-specifiers declarator = ( ( ( additive-expression  declaration-specifiers declarator = ( ( ( shift-expression  declaration-specifiers declarator = ( ( ( relational-expression  declaration-specifiers declarator = ( ( ( equality-expression  ==  53086475   53086475  )   declaration-specifiers declarator = ( ( ( equality-expression == primary-expression  declaration-specifiers declarator = ( ( ( equality-expression == postfix-expression  declaration-specifiers declarator = ( ( ( equality-expression == unary-expression  declaration-specifiers declarator = ( ( ( equality-expression == cast-expression  declaration-specifiers declarator = ( ( ( equality-expression == multiplicative-expression  declaration-specifiers declarator = ( ( ( equality-expression == additive-expression  declaration-specifiers declarator = ( ( ( equality-expression == shift-expression  declaration-specifiers declarator = ( ( ( equality-expression == relational-expression  declaration-specifiers declarator = ( ( ( equality-expression  declaration-specifiers declarator = ( ( ( AND-expression  declaration-specifiers declarator = ( ( ( exclusive-OR-expression  declaration-specifiers declarator = ( ( ( inclusive-OR-expression  declaration-specifiers declarator = ( ( ( logical-AND-expression  declaration-specifiers declarator = ( ( ( logical-OR-expression  declaration-specifiers declarator = ( ( ( conditional-expression  declaration-specifiers declarator = ( ( ( assignment-expression  declaration-specifiers declarator = ( ( ( expression  )  &&   declaration-specifiers declarator = ( ( primary-expression  declaration-specifiers declarator = ( ( postfix-expression  declaration-specifiers declarator = ( ( unary-expression  declaration-specifiers declarator = ( ( cast-expression  declaration-specifiers declarator = ( ( multiplicative-expression  declaration-specifiers declarator = ( ( additive-expression  declaration-specifiers declarator = ( ( shift-expression  declaration-specifiers declarator = ( ( relational-expression  declaration-specifiers declarator = ( ( equality-expression  declaration-specifiers declarator = ( ( AND-expression  declaration-specifiers declarator = ( ( exclusive-OR-expression  declaration-specifiers declarator = ( ( inclusive-OR-expression  declaration-specifiers declarator = ( ( logical-AND-expression  &&  (   (  (   (  53088651   53088651  ==   declaration-specifiers declarator = ( ( logical-AND-expression && ( ( primary-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( postfix-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( unary-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( cast-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( multiplicative-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( additive-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( shift-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( relational-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( equality-expression  ==  53176715   53176715  )   declaration-specifiers declarator = ( ( logical-AND-expression && ( ( equality-expression == primary-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( equality-expression == postfix-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( equality-expression == unary-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( equality-expression == cast-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( equality-expression == multiplicative-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( equality-expression == additive-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( equality-expression == shift-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( equality-expression == relational-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( equality-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( AND-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( exclusive-OR-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( inclusive-OR-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( logical-AND-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( logical-OR-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( conditional-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( assignment-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( ( expression  )  ||   declaration-specifiers declarator = ( ( logical-AND-expression && ( primary-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( postfix-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( unary-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( cast-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( multiplicative-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( additive-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( shift-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( relational-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( equality-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( AND-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( exclusive-OR-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( inclusive-OR-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( logical-AND-expression  declaration-specifiers declarator = ( ( logical-AND-expression && ( logical-OR-expression   此处省略一千多行 这句代码归约出1111行信息（好吉利的数字），由于回复字符不能超过10000个字符串，因此就无法全贴了。LZ想要，可以给个邮箱

何不试试ANTLR， 语法规则与EB解析类但是提供的类更加友好。

引用 1 楼 user-4 的回复:自己 yacc 写个呗, 又不麻烦.略高端，不会玩YACC，有时间学习一下。

引用 5 楼 zhao4zhong1 的回复:参考TCC 老赵你这不按常理出牌啊，你不是应该来一句“仅供参考”然后贴一大段代码的吗？  不过我这边也有点眉目了，可以做出来了

参考TCC

引用 3 楼 lincolnandlinda 的回复:何不试试ANTLR， 语法规则与EB解析类但是提供的类更加友好。 为何都如此高端，有没有C/C++的方式实现的

自己 yacc 写个呗, 又不麻烦.


Question: [SWU]大家帮忙检测下是否完成了要求

flen    = get_file_size(fp); printf("%d\n", flen);

要求是输出长度，不应该有0324.txt file size:等字符，测试程序是不会明白的。 应该考虑一下怎样写一个程序来测试就知道为何了。

仅供参考

lly@Debian:~$ vi 0324.txt (输入1234567890) 后切换到命令模式下输入“:wq”保存 lly@Debian:~$ vi 0324.c  #include <stdio.h> #include <string.h>  #define FILE_NAME       "0324.txt" #define BUF_SIZE        50 #define FILE_NOT_FOUND  -1 #define SUB_STR_FOUND   1 #define SUB_STR         "ac"   int get_file_size(FILE *fp); void get_file_content(FILE *fp, char *buf); int find_substr(const char *buf, const char *substr); void sort_inverted_sequence(char *buf, int size);   int main(void) {         int rev;         FILE *fp;         char buf[BUF_SIZE];         unsigned long int flen;          rev     = 0;          fp      = fopen(FILE_NAME, "r");         if (NULL == fp) {                 rev     = FILE_NOT_FOUND;                 return rev;         }          flen    = get_file_size(fp);         printf("%s file size: %d\n", FILE_NAME, flen);          if (0 < flen <= BUF_SIZE + 1) { //EOF byte                 get_file_content(fp, buf);                  rev     = find_substr(buf, SUB_STR);                  sort_inverted_sequence(buf, flen - 1);                 printf("%s", buf);         }         return rev; }   //Get file's size //fp is the pointer which point the file opened int get_file_size(FILE *fp) {         unsigned long filesize = -1;          fseek(fp, 0L, SEEK_END);        //Small file         filesize        = ftell(fp);          fseek(fp, 0L, SEEK_SET);        //fp point the first char again         return filesize; //Contain EOF byte }   //Read file in buf //fp is pointer of file //buf used save string in file //Use if after get_file_size() void get_file_content(FILE *fp, char *buf) {         int i;         for (i = 0; !feof(fp); ++i) {                 buf[i]  = fgetc(fp);         }         buf[i - 1]      = '\0'; //buf[i - 1] is EOF, End by 0 }   //Find the substring //substr is the substring which find in buf int find_substr(const char *buf, const char *substr) {         char *p;         p       = strstr(buf, substr);         if (NULL != p) return SUB_STR_FOUND;         return 0; }   //Sort the buf by big to small //buf is the sequence will be sorted //size if the size of buf void sort_inverted_sequence(char *buf, int size) {         int i, j, k;         char temp;          for (i = 0; i < size - 1; i++) {        //Small sequence                 k       = i;                 for(j = i + 1; j < size; j++) {                        if (buf[i] < buf[j]) {                                k        = j;                        }                 }                  if (i != k) {                         temp    = buf[i];                         buf[i]  = buf[k];                         buf[k]  = temp;                 }         } }    lly@Debian:~$ gcc 0324.c lly@Debian:~$ ./a.out 0324.txt file size: 11 9876543210 lly@Debian:~$ echo $? 0 lly@Debian:~$

师兄帅气~！！

0319.txt  中存放  的是  1234567890


Question: error: ‘BQ24196_charger_pdata’ undeclared (first use in this function)

谢谢。。。。

data = devm_kzalloc(&client->dev,sizeof(*(BQ24196_charger_pdata)), GFP_KERNEL); 改为 data = devm_kzalloc(&client->dev,sizeof(struct BQ24196_charger_pdata), GFP_KERNEL); 或者 data = devm_kzalloc(&client->dev,sizeof(*(data)), GFP_KERNEL);


Question: C语言问题

不知道算法是怎么的，这样很难猜 这样子赋值有什么深意 啊？

单独一个语句拿出来，估计就是神仙也不知道这个有什么用。

switch(rand()%10)//随机产生图形  			{ 	        case 0:printf("★");b[i][j]=0;++a[0];continue; 			case 1:printf("◆");b[i][j]=1;++a[1];continue; 			case 2:printf("■");b[i][j]=2;++a[2];continue; 			case 3:printf("▲");b[i][j]=3;++a[3];continue; 			case 4:printf("〓");b[i][j]=4;++a[4];continue; 			case 5:printf("卍");b[i][j]=5;++a[5];continue; 			case 6:printf("☆");b[i][j]=6;++a[6];continue; 			case 7:printf("◎");b[i][j]=7;++a[7];continue; 			case 8:printf("♀");b[i][j]=8;++a[8];continue; 			case 9:printf("※");b[i][j]=9;++a[9];continue; 这是个连连看程序的一部分，就是不懂b[i][j]是什么意思

相信switch的外面有个循环。

switch 中能用 continue; 吗

单独一个语句拿出来，估计就是神仙也不知道这个有什么用。


Question: 一道C语言题

引用 6 楼 Beinggeeks 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] va_arg, va_end, va_start Access variable-argument lists.  type va_arg( va_list arg_ptr, type );  void va_end( va_list arg_ptr );  void va_start( va_list arg_ptr );   (UNIX version)  void va_start( va_list arg_ptr, prev_param );   (ANSI version)  Routine Required Header Optional Headers Compatibility  va_arg <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT  va_end <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT  va_start <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT    1 Required for UNIX V compatibility.  For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  va_arg returns the current argument; va_start and va_end do not return values.  Parameters  type  Type of argument to be retrieved  arg_ptr  Pointer to list of arguments  prev_param  Parameter preceding first optional argument (ANSI only)  Remarks  The va_arg, va_end, and va_start macros provide a portable way to access the arguments to a function when the function takes a variable number of arguments. Two versions of the macros are available: The macros defined in STDARG.H conform to the ANSI C standard, and the macros defined in VARARGS.H are compatible with the UNIX System V definition. The macros are:  va_alist  Name of parameter to called function (UNIX version only)  va_arg  Macro to retrieve current argument  va_dcl  Declaration of va_alist (UNIX version only)  va_end  Macro to reset arg_ptr  va_list  typedef for pointer to list of arguments defined in STDIO.H  va_start  Macro to set arg_ptr to beginning of list of optional arguments (UNIX version only)  Both versions of the macros assume that the function takes a fixed number of required arguments, followed by a variable number of optional arguments. The required arguments are declared as ordinary parameters to the function and can be accessed through the parameter names. The optional arguments are accessed through the macros in STDARG.H or VARARGS.H, which set a pointer to the first optional argument in the argument list, retrieve arguments from the list, and reset the pointer when argument processing is completed.  The ANSI C standard macros, defined in STDARG.H, are used as follows:   All required arguments to the function are declared as parameters in the usual way. va_dcl is not used with the STDARG.H macros.   va_start sets arg_ptr to the first optional argument in the list of arguments passed to the function. The argument arg_ptr must have va_list type. The argument prev_param is the name of the required parameter immediately preceding the first optional argument in the argument list. If prev_param is declared with the register storage class, the macro’s behavior is undefined. va_start must be used before va_arg is used for the first time.   va_arg retrieves a value of type from the location given by arg_ptr and increments arg_ptr to point to the next argument in the list, using the size of type to determine where the next argument starts. va_arg can be used any number of times within the function to retrieve arguments from the list.   After all arguments have been retrieved, va_end resets the pointer to NULL.  The UNIX System V macros, defined in VARARGS.H, operate somewhat differently:   Any required arguments to the function can be declared as parameters in the usual way.   The last (or only) parameter to the function represents the list of optional arguments. This parameter must be named va_alist (not to be confused with va_list, which is defined as the type of va_alist).   va_dcl appears after the function definition and before the opening left brace of the function. This macro is defined as a complete declaration of the va_alist parameter, including the terminating semicolon; therefore, no semicolon should follow va_dcl.   Within the function, va_start sets arg_ptr to the beginning of the list of optional arguments passed to the function. va_start must be used before va_arg is used for the first time. The argument arg_ptr must have va_list type.   va_arg retrieves a value of type from the location given by arg_ptr and increments arg_ptr to point to the next argument in the list, using the size of type to determine where the next argument starts. va_arg can be used any number of times within the function to retrieve the arguments from the list.   After all arguments have been retrieved, va_end resets the pointer to NULL.  Example  /* VA.C: The program below illustrates passing a variable  * number of arguments using the following macros:  *      va_start            va_arg              va_end  *      va_list             va_dcl (UNIX only)  */  #include <stdio.h> #define ANSI            /* Comment out for UNIX version     */ #ifdef ANSI             /* ANSI compatible version          */ #include <stdarg.h> int average( int first, ... ); #else                   /* UNIX compatible version          */ #include <varargs.h> int average( va_list ); #endif  void main( void ) {    /* Call with 3 integers (-1 is used as terminator). */    printf( "Average is: %d\n", average( 2, 3, 4, -1 ) );     /* Call with 4 integers. */    printf( "Average is: %d\n", average( 5, 7, 9, 11, -1 ) );     /* Call with just -1 terminator. */    printf( "Average is: %d\n", average( -1 ) ); }  /* Returns the average of a variable list of integers. */ #ifdef ANSI             /* ANSI compatible version    */ int average( int first, ... ) {    int count = 0, sum = 0, i = first;    va_list marker;     va_start( marker, first );     /* Initialize variable arguments. */    while( i != -1 )    {       sum += i;       count++;       i = va_arg( marker, int);    }    va_end( marker );              /* Reset variable arguments.      */    return( sum ? (sum / count) : 0 ); } #else       /* UNIX compatible version must use old-style definition.  */ int average( va_alist ) va_dcl {    int i, count, sum;    va_list marker;     va_start( marker );            /* Initialize variable arguments. */    for( sum = count = 0; (i = va_arg( marker, int)) != -1; count++ )       sum += i;    va_end( marker );              /* Reset variable arguments.      */    return( sum ? (sum / count) : 0 ); } #endif   Output  Average is: 3 Average is: 8 Average is: 0   Argument Access Routines  See Also   vfprintf太高大上了，问题是我怎么能有耐心看懂它[/quote] 英语也是一门计算机语言的说。

这段代码是用于统计后面两个参数二进制形式下有多少个1

va_arg 、va_start 需要一点点栈的知识，如果不明白，先补一下，如果明白，往下看 函数调用参数全部压栈，函数本身没法知道有几个参数，所以第一个n表示传了几个参数，看你的调用不对。 参数在栈中是连续的，va_start是根据n的地址得到下一个参数的地址 va_arg是得到当前参数，并且p'指向下一参数的地址，此处地址均指栈

引用 1 楼 zhao4zhong1 的回复:va_arg, va_end, va_start Access variable-argument lists.  type va_arg( va_list arg_ptr, type );  void va_end( va_list arg_ptr );  void va_start( va_list arg_ptr );   (UNIX version)  void va_start( va_list arg_ptr, prev_param );   (ANSI version)  Routine Required Header Optional Headers Compatibility  va_arg <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT  va_end <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT  va_start <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT    1 Required for UNIX V compatibility.  For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  va_arg returns the current argument; va_start and va_end do not return values.  Parameters  type  Type of argument to be retrieved  arg_ptr  Pointer to list of arguments  prev_param  Parameter preceding first optional argument (ANSI only)  Remarks  The va_arg, va_end, and va_start macros provide a portable way to access the arguments to a function when the function takes a variable number of arguments. Two versions of the macros are available: The macros defined in STDARG.H conform to the ANSI C standard, and the macros defined in VARARGS.H are compatible with the UNIX System V definition. The macros are:  va_alist  Name of parameter to called function (UNIX version only)  va_arg  Macro to retrieve current argument  va_dcl  Declaration of va_alist (UNIX version only)  va_end  Macro to reset arg_ptr  va_list  typedef for pointer to list of arguments defined in STDIO.H  va_start  Macro to set arg_ptr to beginning of list of optional arguments (UNIX version only)  Both versions of the macros assume that the function takes a fixed number of required arguments, followed by a variable number of optional arguments. The required arguments are declared as ordinary parameters to the function and can be accessed through the parameter names. The optional arguments are accessed through the macros in STDARG.H or VARARGS.H, which set a pointer to the first optional argument in the argument list, retrieve arguments from the list, and reset the pointer when argument processing is completed.  The ANSI C standard macros, defined in STDARG.H, are used as follows:   All required arguments to the function are declared as parameters in the usual way. va_dcl is not used with the STDARG.H macros.   va_start sets arg_ptr to the first optional argument in the list of arguments passed to the function. The argument arg_ptr must have va_list type. The argument prev_param is the name of the required parameter immediately preceding the first optional argument in the argument list. If prev_param is declared with the register storage class, the macro’s behavior is undefined. va_start must be used before va_arg is used for the first time.   va_arg retrieves a value of type from the location given by arg_ptr and increments arg_ptr to point to the next argument in the list, using the size of type to determine where the next argument starts. va_arg can be used any number of times within the function to retrieve arguments from the list.   After all arguments have been retrieved, va_end resets the pointer to NULL.  The UNIX System V macros, defined in VARARGS.H, operate somewhat differently:   Any required arguments to the function can be declared as parameters in the usual way.   The last (or only) parameter to the function represents the list of optional arguments. This parameter must be named va_alist (not to be confused with va_list, which is defined as the type of va_alist).   va_dcl appears after the function definition and before the opening left brace of the function. This macro is defined as a complete declaration of the va_alist parameter, including the terminating semicolon; therefore, no semicolon should follow va_dcl.   Within the function, va_start sets arg_ptr to the beginning of the list of optional arguments passed to the function. va_start must be used before va_arg is used for the first time. The argument arg_ptr must have va_list type.   va_arg retrieves a value of type from the location given by arg_ptr and increments arg_ptr to point to the next argument in the list, using the size of type to determine where the next argument starts. va_arg can be used any number of times within the function to retrieve the arguments from the list.   After all arguments have been retrieved, va_end resets the pointer to NULL.  Example  /* VA.C: The program below illustrates passing a variable  * number of arguments using the following macros:  *      va_start            va_arg              va_end  *      va_list             va_dcl (UNIX only)  */  #include <stdio.h> #define ANSI            /* Comment out for UNIX version     */ #ifdef ANSI             /* ANSI compatible version          */ #include <stdarg.h> int average( int first, ... ); #else                   /* UNIX compatible version          */ #include <varargs.h> int average( va_list ); #endif  void main( void ) {    /* Call with 3 integers (-1 is used as terminator). */    printf( "Average is: %d\n", average( 2, 3, 4, -1 ) );     /* Call with 4 integers. */    printf( "Average is: %d\n", average( 5, 7, 9, 11, -1 ) );     /* Call with just -1 terminator. */    printf( "Average is: %d\n", average( -1 ) ); }  /* Returns the average of a variable list of integers. */ #ifdef ANSI             /* ANSI compatible version    */ int average( int first, ... ) {    int count = 0, sum = 0, i = first;    va_list marker;     va_start( marker, first );     /* Initialize variable arguments. */    while( i != -1 )    {       sum += i;       count++;       i = va_arg( marker, int);    }    va_end( marker );              /* Reset variable arguments.      */    return( sum ? (sum / count) : 0 ); } #else       /* UNIX compatible version must use old-style definition.  */ int average( va_alist ) va_dcl {    int i, count, sum;    va_list marker;     va_start( marker );            /* Initialize variable arguments. */    for( sum = count = 0; (i = va_arg( marker, int)) != -1; count++ )       sum += i;    va_end( marker );              /* Reset variable arguments.      */    return( sum ? (sum / count) : 0 ); } #endif   Output  Average is: 3 Average is: 8 Average is: 0   Argument Access Routines  See Also   vfprintf太高大上了，问题是我怎么能有耐心看懂它

百度: c语言 变参函数

此题结果应该是2，你主函数里的函数传参的时候搞错了 ripple(3, 5, 7) 第一个参数表示的是 后面应该传递的参数个数 ，你这么写的意思就是告诉编译器你传递 3 个参数 而后面你只传递了两个参数，所以第一个参数应该是2     ripple(2, 5, 7)  。

这段程序的作用是用来计算出ripple()函数从第二个参数开始后面所有参数int形式的使用二进制表示时，每个二进制数中有多少个1，va_arg 、va_start是用来读取ripple()的可变参数的。

#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) ) #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //第一个可选参数地址 #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数地址 #define va_end(ap) ( ap = (va_list)0 ) // 将指针置为无效


Question: 二级指针无法释放

楼主程序对内存释放部分应该没问题，至于在函数中设置 myarray = NULL 但是在main函数中myarray却不是NULL， 这点需要注意的是：函数形参传递的只是值而非变量地址，如果我们想更改该变量的值，需要把该变量的地址传递过去。

C语言是单向值传递，main函数中myarray的值并未改变，但个人觉得内存是释放了的。三级指针试试

if (myarray[i] != NULL)         {             free(myarray[i][]);         }

“free后，myarray的地址没有被释放”内存已经被释放了，只是myarray还是指向旧地址，但并不表明这块内存还可以用

用三级指针吧。楼上的楼上。

释放之后，需要指向NULL。 建议统一管理所用到的指针。

内存释放不释放不是看指针是否为NULL的，把指针赋NULL只是为了说明此指针所指内存已不可用，防止非法访问。 对于你的释放函数，如果真的想把 myarray 的值传出去用于判断是否已释放内存的话的话，你应该用地址形式。  像如下一样：  /************************************************************************/ /* 释放内存                                                                     */ /************************************************************************/ void freeArray(char ***myarray,int n){     int i = 0;     if (*myarray == NULL){         return ;     }     for(i = 0; i < n;i++){          if ((*myarray)[i] != NULL)         {             free((*myarray)[i]);         }     }      if(*myarray != NULL){         free(*myarray);     }     *myarray = NULL; }  // 调用 freeArray(&myarray,10);

执行完free函数之后，确实会将内存释放，但不会将myarray置为NULL，因为myarray存储在栈上，此时是一个野指针，需要手动置空。

引用 楼主 laopufua 的回复:  #include <stdlib.h> #include <stdio.h> #include <string.h> /************************************************************************/ /* 分配内存                                                                     */ /************************************************************************/ char **arrayCreate(int n){ 	int i = 0; 	char **myarray = NULL; 	myarray = (char**)malloc(n*sizeof(char*)); 	if(myarray == NULL){ 		return NULL; 	} 	for(i = 0; i < 10; i++){ 		myarray[i] = (char*)malloc(10*sizeof(char)); 	} 	return myarray; }/************************************************************************/ /* 释放内存                                                                     */ /************************************************************************/ void freeArray(char **myarray,int n){ 	int i = 0; 	if (myarray == NULL){ 		return ; 	} 	for(i = 0; i < n;i++){  		if (myarray[i] != NULL) 		{ 			free(myarray[i]); 		} 	}  	if(myarray != NULL){ 		free(myarray); 	} 	myarray = NULL; }      int main(){ 	int n = 10; 	char **myarray = NULL; 	 	myarray = arrayCreate(10); 	freeArray(myarray,10); 	 	  	if (myarray == NULL){ 		printf("内存已经释放完毕！\n"); 	}  	system("pause");  }     断点调试，myarray分配内存后，可以获取地址，free后，myarray的地址没有被释放，还是之前的地址。指针传入参数后，执行后，不管用？传入的指针参数，无法修改吗？  楼主内存已经正确释放，问题仅仅出在参数传递上。  myarray 保存的是 分配的内存地址，释放这个内存之后要想改变myarray的值，要有myarray的地址。  也就是说改成：void freeArray(char ***myarray,int n);  把&myarray传递过去，函数最后*myarray = NULL，即可达成你想要的效果。

仅供参考：#include <stdio.h> #include <stdlib.h> #include <malloc.h> int **newarr2d(int rows,int cols) {     int **p,i;      p=(int **)malloc(rows*sizeof(int *));     if (NULL==p) exit(1);     for (i=0;i<rows;i++) {         p[i]=(int *)malloc(cols*sizeof(int));         if (NULL==p[i]) exit(1);     }     return p; } void deletearr2d(int **p,int rows) {     int i;      for (i=0;i<rows;i++) {         free(p[i]);     }     free(p); } int main() {     int **arr2d,i,j,r,c;      r=4;     c=5;     //在堆中开辟一个4×5的二维int数组     arr2d=newarr2d(r,c);     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             arr2d[i][j]=i*c+j;         }     }     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             printf(" %2d",arr2d[i][j]);         }         printf("\n");     }     deletearr2d(arr2d,r);      r=6;     c=3;     //在堆中开辟一个6×3的二维int数组     arr2d=newarr2d(r,c);     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             arr2d[i][j]=i*c+j;         }     }     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             printf(" %2d",arr2d[i][j]);         }         printf("\n");     }     deletearr2d(arr2d,r);      return 0; } //  0  1  2  3  4 //  5  6  7  8  9 // 10 11 12 13 14 // 15 16 17 18 19 //  0  1  2 //  3  4  5 //  6  7  8 //  9 10 11 // 12 13 14 // 15 16 17 //


Question: 结构体的小问题

引用 2 楼 ilinfe 的回复:[quote=引用 1 楼 u010005508 的回复:] 这里肯定有个主要的参考字段，假设你将班级号当主要参考，那么只有当两组数据的班级号相同时，你才需要去比较他们的序号(按升序排)，否侧就是根据班级号来升序排的！ 反过来假如你将序号当主要参考，那么也是类似的！ ps:假如这里没有啥主次之分，那就需要你自己定义一个根据班级号和序号排序的算法  班级号是主要参考，排好班级以后要排班级里面同学的序号，我不知道该怎么排[/quote] 给个简单示例，你参考下吧，主要就是compare_student()函数 #include <iostream> using namespace std; struct Student { 	int ClassNumber; 	int Number; 	char Name[20]; };  int compare_student(Student a,Student b)//定义比较大小的函数，a>b返回1，a=b返回0，a<b返回-1 { 	if(a.ClassNumber==b.ClassNumber) 	{ 		return a.Number>b.Number?1:(a.Number==b.Number?0:-1); 	} 	else 	{ 		return a.ClassNumber>b.ClassNumber?1:-1; 	} }  void sort_student(Student* pStudent,int num) { 	Student temp; 	for(int i=0;i<num;i++) 	{ 		for(int j=i;j<num-1;++j) 		{ 			if(compare_student(pStudent[j],pStudent[j+1])==1) 			{ 				temp=pStudent[j]; 				pStudent[j]=pStudent[j+1]; 				pStudent[j+1]=temp; 			} 		} 	} }  void print_student(Student* pStudent,int num) { 	for(int i=0;i<num;++i) 	{ 		cout<<pStudent[i].ClassNumber<<ends<<pStudent[i].Number<<ends<<pStudent[i].Name<<endl;; 	} } void main() { 	Student students[4]; 	for(int i=0;i<4;++i) 	{ 		sprintf(students[i].Name,"%s%d","name",i+1); 	} 	students[0].ClassNumber=1; 	students[0].Number=4; 	students[1].ClassNumber=1; 	students[1].Number=3; 	students[2].ClassNumber=2; 	students[2].Number=3; 	students[3].ClassNumber=3; 	students[3].Number=2; 	sort_student(students,4); 	print_student(students,4); }

这位朋友，不知道你的数据结构是如何实现，就我对你描述的需求的理解，你貌似要求输出的样子是首先班级号是有序的，其次在同一个班级号中，序号是有序的。 那么小弟拙见，我觉得没必要排两次，你可以这样，把班级号和序号组合成一个数，假如班级号和序号最多都到99，那么班级号11，序号23可以组合为1123，同理，班级号3，序号17可以组合为0317(即317)，然后你再对这个组合数进行排序，不是很简单而且只需要排一次。等排完了，你再把组合数拆开再去打印即可。 不过，只是基于我对于此需求的理解，如果理解错了，这个方法就没用了。

if (a.class_number> b.class_number || (a.class_number==b.class_number && a.number>b.number)) {    //TODO:交换a，b   // }

引用 1 楼 u010005508 的回复:这里肯定有个主要的参考字段，假设你将班级号当主要参考，那么只有当两组数据的班级号相同时，你才需要去比较他们的序号(按升序排)，否侧就是根据班级号来升序排的！ 反过来假如你将序号当主要参考，那么也是类似的！ ps:假如这里没有啥主次之分，那就需要你自己定义一个根据班级号和序号排序的算法  班级号是主要参考，排好班级以后要排班级里面同学的序号，我不知道该怎么排