关于c:理解C语言中的aa和aa

C语言中 a++ a-- 和 ++a --a 的区别a++ 示意先赋值再进行加运算a-- 示意先赋值再进行减运算++a 示意先进行加运算再赋值--a 示意先进行减运算再赋值注:从下面的概念了解很形象实例1. 了解 a++ 代码# include <stdio.h>int main(){ int a = 10; int c ; // 第一次间接给 c 赋值 c = a = 10,第二次再计算赋值给 a ,即 a = a + 1 = 10 + 1 = 11 c = a++; printf("先赋值再运算 \n"); printf("此时 c 的值为:%d", c); printf("此时 a 的值为:%d", a); return 0;}计算结果如下: 先赋值再运算此时 c 的值为:10此时 a 的值为:112. 了解 a-- 代码# include <stdio.h>int main(){ int a = 10; int c ; // 第一次间接给 c 赋值 c = a = 10,第二次再计算赋值给 a ,即 a = a - 1 = 10 - 1 = 9 c = a--; printf("先赋值再运算 \n"); printf("此时 c 的值为:%d", c); printf("此时 a 的值为:%d", a); return 0;}计算结果如下: ...

March 30, 2022 · 2 min · jiezi

关于c:CC-用什么软件编程

一款不便棘手的编程软件对于 C/C++ 开发者们来说,无疑会节俭十分多不必要的环境装置和学习应用教程的工夫。看到一些答复围绕不同操作系统,举荐了不同的IDE。我在这里给大家介绍一个全平台都通用、轻量且功能强大的在线编辑器 Lightly。它是首个依据中国开发者应用习惯量身打造的 IDE 编程软件,界面风格简洁明快。 在 Lighlty 上用户不须要配置任何编译运行环境,抉择开发语言后即可开始写代码。代码和我的项目文件能够实时保留在云端的,换台不同零碎的电脑或者是用平板,也能够关上我的项目,持续编码。 进入 Lightly 官网,能够抉择在线应用或者下载Mac和Windows本地版。 Lightly 不仅所有语言界面都有中文,而且反对手机或者QQ、微信扫码登录,十分中央便。(一键体验) 抉择我的项目语言后,零碎会主动生成对应的开发环境,你只须要在工作区域间接写代码就行。Lightly同样反对高亮显示、智能提醒、主动补全等性能。操作笨重灵便,应用便捷,开发效率高,是十分完满的 C/C++ 编程软件。 除此之外,他还具备我的项目一键分享性能:只需点击界面右上角头像旁边的“增加成员”按钮,生成并分享链接给小伙伴,他们就能够退出我的项目一起写代码啦!Lightly 对于有团队合作需要的开发者来说,也是最合适的抉择。

March 29, 2022 · 1 min · jiezi

关于c:MIPS-simulator-项目

Project 1 OverviewThe first project is going to be a MIPS simulator. In general, you will be building a program thatsimulates the execution of an assembly language file. The input of your program will be a MIPSfile that contains MIPS assembly language code. Examples will be given in the latter part of thisinstruction.1.1 Readings:Please read Appendix A from the text book before you start writing your first project. Make sureyou understand what each MIPS instruction is doing. All of the supplementary materials for thisproject can be found in Appendix A, such as the register numbers, instructions, and their machinecode format.MIPSMIPS is an assembly language, which is a low level programming language that each line ofcode corresponds to one machine instruction.2.1 InstructionMachines cannot understand high level programming languages directly, such as C/C++/JAVA.High level programming languages are "translated" to machine instructions that machine canunderstand. Assembly languages, including MIPS we deal with, are the readable (althoughdifficult) version of machine code. In assembly languages, one instruction tells the computer to doone thing exactly. For example, an instruction may look like this:This instruction tells the computer to add up the things stored in register $t1 and register $t2and store the result in $t3. Here, registers are small chunks of memory in CPU used for programexecution. The MIPS assembly language has three types of instruction in general: I-type, R-type,and J-type, each corresponds to a pattern of the 32 bits of machine code. Details can be found inAppendix A of the text book. The above instruction has the machine code:It does not make sense at a glance, however, it follows a certain pattern. The add instruction isa R-instruction, so it follows the pattern of:add $t0, $t1, $t200000001001010100100000000100000R-instruction:op rs rt rd shamt funct| 6bits | 5bits | 5bits | 5bits | 5bits | 6bits |op: operation code, all zeros for R-instructions.rs: the first register operandrt: the second register operandrd: the destination registershamt: shift amount. 0 when N/AHere, we go through how this instruction and its machine code corresponds to each other.The first 6 bits for R-instruction are for operation code, which are all zeros for R-type.The following three 5-bit slots are the register numbers specified in the instruction. "rs" and"rt" represents the first and second register operand in the instruction, and "rd" representsthe destination register. Here, the register number of $t0, $t1, and $t2 are 8, 9, 10,respectively. These translate to 01000, 01001, 01010 in binary, respectively. Putting them inthe right place, we have the middle 15-bits."shamt" represents the shift amount, which are only in certain instructions (such as sll, srl),and 0's are filled when N/A. In add instruction, these 5 bits are zeros.The last 6 bits are for function code. The function code for add is 32, which is 100000 inbinary.Machine codes of other R-instructions are constructed through the same process. As for Iinstructionsand J-instructions, I will not go through an example. The formats of these two types ofinstructions are:2.2 MIPS programsNow you know what do MIPS instructions look like, but what does a MIPS program look like?Here is a general format a MIPS program follows:funct: function code, which is used to identify which R-instruction this is.The add instruction has the format:add $rd, $rs, $rtTherefore, for add $t0, $t1, $t2, we have:01001 01010 01000 00000 100000I-instruction:op rs rt immediate| 6bits | 5bits | 5bits | 16bits |op: the operation code that specifies which I-instruction this is.rs: register that contains the base addressrt: the destination/source register (depends on the operation)immediate: a numerical value or offset (depends on the operation)J-instruction:op address| 6bits | 26bits |op: the operation code that specifies which J-instruction this is.address: the address to jump to, usually associate with a label. Since theaddress of an instruction in the memory is always divisible by 4 (think aboutwhy), the last two bits are always zero, so the last two bits are dropped.In general, a MIPS program looks like this. All of the MIPS code goes under the .text section, andall of the static data in the program are under .data section. As you can see, for each piece ofstatic data, we have a name to it, just like what we do in high level programming languages. "str1"is the name to that piece of data, .asciiz is the data type of it, and "hello world!\n" is the value.There are many other types of data, you can find them in Appendix A.For the code part, as you can see, we also have a "name" called "main". This is the labelrepresenting the line of code. Usually this is used for indicating the start of a loop, a function, or aprocedure. Recall that all of these codes are stored somewhere in the memory, which means thateach line of code has a specific address. To better understand this, see section 2.3.2.3 How computer runs the program?With the idea that all of the codes are stored in memory, and each has an address, we can nowtalk about how computers run these codes. Long story short, the computer runs the programsfollowing the machine cycle.2.3.1 Machine cycleA shorter version of a machine cycle looks like this:The computer loads the line of instruction PC is "pointing at".The computer increment PC by 4 (think about why).The computer runs the instruction loaded.This goes on until the program terminates. PC in this context represents the "program counter".In other words, PC is the "pointer" the computer maintains that stores the address of thenext instruction to be executed.Project 1 details3.1 RequirementsYour project 1 should be written in C/C++ only.You will need to write your own makefile/cmake.The testing environment is provided by Mr. Yifan Zhu and Mr. Guochao Xie. You need tomake sure your program can execute without a problem on the VM/Docker they provided.You can access the testing environment through VM instruction on BB.The detailed list of the MIPS instructions you need to support will be announced later.3.2 Assembler.data #static data go herestr1: .asciiz "hello world!\n".text #MIPS code goes heremain: add $t0, $t1, $t2...3.2.1 OverviewThe first task you are doing is assembling the given MIPS code to their corresponding machinecode. Here's a quick example of what you need to do:Remember that you are not assembling the .data section, nor the labels. The .data section willbe loaded to your memory in your simulation part. The labels in your .text section will betranslated to its corresponding address when needed. For example, when you see j R , you willput the address of the line of instruction label R is indicating.3.2.2 DetailsThis part of your program is easy but needs your patience. You need to be able to:Read file line by line.Find the segments of the MIPS file. (.data, .text)Tokenize the line read in.Discard useless information, such as comments.Here are some ideas of how to implement this part:You need to scan through the file for the first time. This time, discard all of the comments(following a "#"). Remember you only need to deal with .text segment for assembling. Find allof the labels in the code, and store them with their corresponding address for laterreference.You need to scan through the file for the second time, line by line. This time, you need toidentify which instruction the line is (R, I, J). According to the instruction type, you canassemble the line. For lines with the label, you can refer to the stored information for thelabel's address.3.3 Simulator3.3.1 OverviewThis is the major part of your project 1. You need to have a full understanding of how computerexecutes programs, and how are things stored in memory. Your code will need to be capable ofexecuting the MIPS code line by line.MIPS code:.textR: add $s0, $s1, $s2 #r instructionsaddu $s0, $s1, $s2sub $s0, $s1, $s2subu $s0, $s1, $s2Machine code:000000100011001010000000001000000000001000110010100000000010000100000010001100101000000000100010000000100011001010000000001000113.3.2 Memory & register simulationThe first thing you will need to do is memory simulation. Think about your simulator as a minicomputer,that has its own main memory, CPU, etc. To simulate main memory, you need todynamically allocate a block of memory with C/C++, with a size of 6MB. Here is a figure of whatdoes a real computer memory look like.Your simulated memory should also have these components. Also, since most of you are usinga 64-bit computer, you need to "translate" the real address of your allocated memory to a 32-bitsimulated address. Specifically:Let's say you have the pointer named "real_mem" storing the real address of the block ofmemory allocated. The first thing you need to do is to map the value of "real_mem" to400000_hex. Then the real address will have a 1-to-1 mapping relationship to the simulatedaddress. For instance, if the address mentioned in the MIPS testing file is 500000_hex (suchas lw, where we want to load the data storing on 500000_hex), then, you should access it atreal address of: (real_mem + 500000_hex - 400000_hex).The dynamically allocated 6MB memory block is pointing at the start of your text segment,and your text segment will be 1MB in size. The end of text segment will be at simulatedaddress 400000_hex+1MB, or at address real_mem+1MB.The static data segment will start at simulated address 500000_hex, or at real address(real_mem+1MB).The dynamic data segment will start at wherever your static data section ends.The stack segment will start at the highest address 1000000_hex (real_mem+6MB), and itgrows downwards (whenever you put things in there, the address decreases).You should also simulate the registers. The registers should not be a part of your simulatedmemory. Recall that registers are in CPU. In this project, you are not accessing the real registers,however, you will allocate memory for the 32 general purpose registers, which are:Your code should initiate the registers as described by its functionality. For example, the stackpointer register, $sp, should always store the current stack top. You should initialize it with a valueof 1000000_hex.3.3.3 Putting things in the right placeYour simulator should take a MIPS file as input, and you should put everything in the right placebefore your simulation. After the simulated memory is ready, you will read a MIPS file, and:Put the data in .data segment of MIPS file piece by piece in the static data segment. Thewhole block (4 bytes) is assigned to a piece of data even if it is not full. For example:Here, each character of .asciiz type occupies 1 byte, so "hell" occupies the first block. The firsttwo bytes of the second block is used by "o" and a terminating sign "\0", but the last twobytes of the second block is not used. However, when we put the next piece of data in thememory, we start a new block. The data type .word occupies 4 bytes, so the third block isassigned to this piece of data.Assemble the .text segment of the MIPS file (section 3.2), and put the assembled machinecode in the text segment of your simulated memory (the first line of code has the lowestaddress). The assembled machine code is 32 bits, which is 4 bytes. Thus, you can translate itto a decimal number and store it as an integer.3.3.4 Start simulatingYour code should maintain a PC, which points to the first line of code in the simulated memory.Your code should have a major loop, simulating the machine cycle. Following the machine cycle,your code should be able to:Go to your simulated memory to fetch a line of machine code stored at the address PCindicates.PC=PC+4From the machine code, be able to know what the instruction is and do the correspondingthings.The third step of the machine cycle requires you to write a C/C++ function for each instruction todo what it's supposed to. For example, for the add instruction, we can write in C:In the third step of the machine cycle, when we read a line of machine code and thecorresponding instruction is add , we can simply call the function.Miscellaneous.datastr1: .asciiz "hello"int1: .word 1in memory:| hell | o\0-- | 1 |void add (int rs, int rt, int* rd){rd = rs+ *rt;}4.1 DeadlineThe deadline of this project is 3/21/2021 midnight.4.2 SubmissionYou should put all of your source files in a folder and compress it in a zip. Name it with yourstudent ID. Submit it through BB.4.3 GradingThis project worth 30% of your total grade. The grading details of this project will be:Assembling - 20%Memory & register simulation - 30%Proper MIPS execution - 40%Each unsuccessful MIPS instruction will result in 3% deduction.Report - 10%NOTICE: If your code does not support makefile/cmake, you will lose 50% automatic.4.4 ReportThe report of this project should be no longer than 5 pages.In your report, you should write:Your big picture thoughts and ideas, showing us you really understand how are MIPSprograms executed in computers. (This part should be the major part of your report.)The high level implementation ideas. i.e. how you break down the problem into smallproblems, and the modules you implemented, etc.The implementation details. i.e. what structures did you define and how are they used.In your report, you should not:Include too many screenshots your code.Copy and paste others' report.4.5 HonestyWe take your honesty seriously. If you are caught copying others' code, you will get anautomatic 0 in this project. Please write your own code.WX:codehelp

March 29, 2022 · 11 min · jiezi

关于c:从Minix中学到的C语言小技巧

在global.h中应用EXTERN申明全局变量,代码如下: #define EXTERN extern#ifdef TABLE #undef EXTERN #define EXTERN#endifEXTERN i32_t tty_pos;EXTERN u8_t gdt_info[6];EXTERN gdesc_t gdt[GDT_SIZE];在table.c中定义TABLE宏,并蕴含global.h,可使得所有的全局变量在table.c中定义,代码如下: #define TABLE/* 所有全局变量在此文件中定义 */#include "global.h"而所有其余蕴含global.h的C文件只蕴含全局变量的申明。

March 28, 2022 · 1 min · jiezi

关于c:CMPSC473-Malloc-Lab

CMPSC473, Spring 2021Malloc Lab: Writing a Dynamic Storage AllocatorAssigned: Feb. 16Checkpoint 1 Due: Sun., Feb. 28,11:59:59 PMCheckpoint 2 Due: Sat., Mar. 06,11:59:59 PMDue: Fri., Mar. 12, 11:59:59PMPlease read this document carefully!1 IntroductionIn this lab, you will be writing a dynamic storage allocator for C programs, i.e., your own version of the malloc,free, and realloc functions. You are encouraged to explore the design space creatively and implement an allocatorthat is correct, space efficient, and fast.The only file you will be modifying is mm.c. Modifications in other files will not be used in the grading. You will beimplementing the following functions:• bool mm init(void)• void* malloc(size t size)• void free(void* ptr)• void realloc(void oldptr, size t size)• bool mm checkheap(int lineno)You are encouraged to define other (static) helper functions, structures, etc. to better structure your code.2 Programming Rules• IMPORTANT: You are required to implement a heap checker (see Section 5) that will be graded. Theheap checker will help you debug your code.• IMPORTANT:You are required to write commentsfor all of your code including the heap checker. Additionally,you need to write a file comment at the top of the file describing your overall malloc design. SeeSection 7 for grading details.• IMPORTANT: You must show your partial work on this assignment by periodically committing andsubmitting (i.e., pushing) your code to git. This will be used both for grading the checkpoints as well asensuring academic integrity.• You are not allowed to change any of the interfaces inmm.c.2• You are not allowed to invoke any memory-management related library calls or system calls. For example, youare not allowed to use sbrk, brk, or the standard library versions of malloc, calloc, free, or realloc.Instead of sbrk, you should use our provided mem sbrk.• Your code is expected to work in 64-bit environments, and you should assume that allocation sizes and offsetswill require 8 byte (64-bit) representations.• You are not allowed to use macros as they can be error-prone. The better style is to use static functions and letthe compiler inline the simple static functions foryou.• You are limited to 128 bytes of global space for arrays, structs, etc. If you need large amounts of space forstoring extra tracking data, you can put it in the heaparea.• IMPORTANT: Failure to abide by these requirements may result in a 0 for the assignment.3 Description of the dynamic memory allocator functions• mm init: Before calling malloc, realloc, calloc, or free, the application program (i.e., the tracedrivendriver program that will evaluate your code) calls your mm init function to perform any necessaryinitializations, such as allocating the initial heap area. The return value should be true on success and false ifthere were any problems in performing the initialization.• malloc: The malloc function returns a pointer to an allocated block payload of at least size bytes. Theentire allocated block should lie within the heap region and should not overlap with any other allocated chunk.If the requested size is 0 or if mem sbrk is unable to extend the heap, then you should return NULL. Similarto how the standard C library (libc) always returns payload pointers that are aligned to 16 bytes, your mallocimplementation should do likewise and always return 16-byte alignedpointers.• free: The free function frees the block pointed to by ptr. It returns nothing. This function is onlyguaranteed to work when the passed pointer (ptr) was returned by an earlier call to malloc, calloc, orrealloc and has not yet been freed. If ptr is NULL, then free should do nothing.• realloc: The realloc function returns a pointer to an allocated region of at least size bytes with thefollowing constraints.– if ptr is NULL, the call is equivalent to malloc(size);– if sizeis equal to zero, the call is equivalent to free(ptr);– if ptr is not NULL, it must have been returned by an earlier call to malloc, calloc, or realloc.The call to realloc changes the size of the memory block pointed to by ptr (the old block) to sizebytes and returns the address of the new block. Notice that the address of the new block might be the sameas the old block, or it might be different, depending on your implementation, the amount of internalfragmentation in the old block, and the size of the reallocrequest.The contents of the new block are the same as those of the old ptr block, up to the minimum of the oldand new sizes. Everything else is uninitialized. For example, if the old block is 8 bytes and the new blockis 12 bytes, then the first 8 bytes of the new block are identical to the first 8 bytes of the old block and thelast 4 bytes are uninitialized. Similarly, if the old block is 8 bytes and the new block is 4 bytes, then thecontents of the new block are identical to the first 4 bytes of the oldblock.These semantics match the the semantics of the corresponding libc malloc, realloc, and free functions. Runman malloc to view complete documentation.34 Support FunctionsThe memlib.c package simulates the memory system for your dynamic memory allocator. You can invoke thefollowing functions in memlib.c:• void* mem sbrk(int incr): Expands the heap by incr bytes, where incr is a positive non-zero integer.It returns a generic pointer to the first byte of the newly allocated heap area. The semantics are identicaltothe Unix sbrk function, except that mem sbrk accepts only a non-negative integer argument.You must use our version, mem sbrk, for the tests to work. Do not use sbrk.• void* mem heap lo(void): Returns a generic pointer to the first byte in the heap.• void* mem heap hi(void): Returns a generic pointer to the last byte in the heap.• size_t mem heapsize(void): Returns the current size of the heap in bytes.• size_t mem pagesize(void): Returns the system’s page size in bytes (4K on Linux systems).• void memset(void ptr, int value, size t n): Sets the first n bytes of memory pointed toby ptr to value.• void memcpy(void dst, const void* src, size t n): Copies n bytes from src to dst.5 Heap Consistency CheckerDynamic memory allocators are notoriously tricky beasts to program correctly and efficiently. They are difficult toprogram correctly because they involve a lot of untyped pointer manipulation and low-level manipulation of bits andbytes. You will find it very helpful to write a heap checker mm checkheap that scans the heap and checks it forconsistency. The heap checker will check for invariants which should always be true.Some examples of what a heap checker might check are:• Is every block in the free list marked asfree?• Are there any contiguous free blocks that somehow escapedcoalescing?• Is every free block actually in the free list?• Do the pointers in the free list point to valid free blocks?• Do any allocated blocks overlap?• Do the pointers in a heap block point to valid heapaddresses?You should implement checks for any invariants you consider prudent. It returns true if your heap is in a valid,consistent state and false otherwise. You are not limited to the listed suggestions nor are you required to check all ofthem. You are encouraged to print out error messages when the check fails. You can use dbg printf to printmessages in your code in debug mode. To enable debug mode, uncomment the line #define DEBUG.To call the heap checker, you can use mm checkheap( LINE ), which will pass in the line number of the caller.This can be used to identify which line detected a problem.You are required to implement a heap checker for your code, both for grading and debugging purposes. SeeSection 7 for details on grading.46 Testing your codeFirst, you need to compile/build your code by running: make. You need to do this every time you change your codefor the tests to utilize your latest changes.To run all the tests after building your code, run: make test.To test a single trace file after building your code, run: ./mdriver -f traces/tracefile.rep.Each trace file contains a sequence of allocate, reallocate, and free commands that instruct the driver to call yourmalloc, realloc, and freefunctions in some sequence.Other command line options can be found by running: ./mdriver -hTo debug your code with gdb, run: gdb mdriver.7 EvaluationYou will receive zero points if:• you break any of the programming rules in Section2• your code does not compile/build• your code is buggy and crashes the driverOtherwise, your grade will be calculated as follows:50 pts Checkpoint 1 (Due: Sun., Feb. 28, 11:59:59 PM): This part of the assignment simply tests the correctness of yourcode. Space utilization and throughput will not be tested in this checkpoint. Your grade will be based on thenumber of trace files that succeed.100 pts Checkpoint 2 (Due: Sat., Mar. 06, 11:59:59 PM): This part of the assignment requires that your code is entirelyfunctional and tests the space utilization (60 pts) and throughput (40 pts) of your code. Each metric will have amin and max target (i.e., goal) where if your utilization/throughputis above the max, you get full score and if itis below the min, you get no points. Partial points are assigned proportionally between the min and max.– Space utilization (60 pts): The space utilization is calculated based on the peak ratio between the aggregateamount of memory used by the driver (i.e., allocated via malloc or realloc but not yet freed via free)and the size of the heap used by your allocator. You should design good policiesto minimize fragmentationin order to increase this ratio.– Throughput (40 pts): The throughput is a performance metric that measures the average number ofoperations completed per second. As the performance of your code can vary between executions andbetween machines, your score as you’re testing your code is not guaranteed. The performance testingwill be performed on the W204 cluster machines to ensure more consistent results.100 pts Final submission (Due: Fri., Mar.12, 11:59:59 PM): This part of the assignment is graded identically as Checkpoint2, except that the grading curve has not been significantly reduced as is the case with Checkpoint 2.50 pts Code demo and comments (Due: Fri., Mar. 12, 11:59:59 PM): As part of the final submission, we will bereviewing your heap checker code and commentsthrough your code. You will need to upload a 4-5 minutedemo video describing your design choice, data structures and heap checker code and upload it on canvas(one demo video per team). The TAs can ask you to schedule an appointment to meet them via zoom toanswer additional questions about your project after the deadline, if necessary. Your heap checker will begraded based on correctness, completeness, and comments. The comments should be understandable to aTA. The demo will show correctness. Your explanation of the heap checker and your malloc design willdetermine the degree to which your checker is checking invariants.5There will be a balance between space efficiency and speed (throughput),so you should not go to extremes to optimizeeither the space utilization or the throughput only. To receive a good score, you must achieve a balance betweenutilization and throughput.Grades will be assigned by running your code on W204 machines. So, please check that your code runs on thosemachines.8 Handin InstructionsYou must show your partial work on this assignment by periodically committing and submitting (i.e., pushing) yourcode to git. To do this, run:git add mm.cgit commit -m "Write a comment here about your code changes"git pushWe will use the latest submission before each deadline as well as the latest submission before each late deadline forgrading purposes. Each checkpoint and final submission can use the late policy, and we will calculate and use thebetter of the normal score and the late score with the late penalty. Thus, make sure you are committing and submittingto git often. If you want to specify a commit for a specific checkpoint, write it in your readme file.You have to submit your demo video as an assignment (Project 2) on Canvas.Additionally, you must submit your github username that you used for the assignment in Canvas (Youshould have done this for project 1. No need to re-submit.).9 Hints• Use the mdriver -f option. During initial development, using tiny trace files will simplify debugging andtesting. We have included some trace files ending in -short.rep that you can use for initial debugging.• Write a good heap checker. This will help detect errors much closer to when they occur. This is one of the mostuseful techniques for debugging data structures like the malloc memory structure.• Use gdb; watchpoints can help with finding corruption. gdb will help you isolate and identify out of boundsmemory references as well as where in the code the SEGFAULT occurs. To assist the debugger, you may wantto compile with make debug to produce unoptimized code that is easier to debug. To revert to optimizedcode, run make release for improved performance. Additionally, using watchpoints in gdb can help detectwhere corruption is occurring if you know the address that is being corrupted.• The textbooks have detailed malloc examples that can help your understanding. You are allowed to referenceany code within the textbooks as long as you cite the source (as comment in your code). However, directlycopying code from online source is strictly forbidden.• Encapsulate your pointer arithmetic and bit manipulation in static functions. Pointer arithmetic in yourimplementation can be confusing and error-prone because of all the casting that is necessary. You can reducethe complexity significantly by writing static functions for your pointer operations and bit manipulation. Thecompiler should inline these simple functions for you.• Use git to track your different versions. git will allow you to track your code changes to help you rememberwhat you’ve done in the past. It can also provide an easy way to revert to prior versions if you made a mistake.• Use the mdriver -v and -V options. These options allow extra debug information to be printed.• Start early! Unless you’ve been writing low-level systems code since you were 5, this will probably be some ofthe most difficult and sophisticated code you have written so far in your career. So start early, and good luck! ...

March 28, 2022 · 11 min · jiezi

关于c:C速成指南从入门到进阶实战WPF与Unity3D开发

download:C#速成指南:从入门到进阶,实战WPF与Unity3D开发备链:https://www.97yrbl.com/t-1374.html 新的计划咱们奇妙地将 FFi 计划与外接纹理计划组合,解决了一系列业务痛点。 FFI正如结尾说的那些问题,Texture 计划有些做不到的事件,这须要其余计划来互补,这其中外围须要的就是 ui.Image。咱们把 native 内存地址、长度等信息传递给 flutter 侧,用于生成 ui.Image。 首先 native 侧先获取必要的参数(以 iOS 为例): _rowBytes = CGImageGetBytesPerRow(cgImage);CGDataProviderRef dataProvider = CGImageGetDataProvider(cgImage);CFDataRef rawDataRef = CGDataProviderCopyData(dataProvider);_handle = (long)CFDataGetBytePtr(rawDataRef);NSData *data = CFBridgingRelease(rawDataRef);self.data = data;_length = data.length;dart 侧拿到后,@override FutureOr<ImageInfo> createImageInfo(Map map) {Completer<ImageInfo> completer = Completer<ImageInfo>();int handle = map['handle'];int length = map['length'];int width = map['width'];int height = map['height'];int rowBytes = map['rowBytes'];ui.PixelFormat pixelFormat = ui.PixelFormat.values[map['flutterPixelFormat'] ?? 0];Pointer<Uint8> pointer = Pointer<Uint8>.fromAddress(handle);Uint8List pixels = pointer.asTypedList(length);ui.decodeImageFromPixels(pixels, width, height, pixelFormat, (ui.Image image) { ImageInfo imageInfo = ImageInfo(image: image); completer.complete(imageInfo); //开释 native 内存 PowerImageLoader.instance.releaseImageRequest(options);}, rowBytes: rowBytes);return completer.future; }咱们能够通过 ffi 拿到 native 内存,从而生成 ui.Image。这里有个问题,尽管通过 ffi 能间接获取 native 内存,然而因为 decodeImageFromPixels 会有内存拷贝,在拷贝解码后的图片数据时,内存峰值会更加重大。 ...

March 22, 2022 · 1 min · jiezi

关于c:ECE-650-Malloc

Assignment #1: Malloc Library Part 1ECE 650 – Spring 2021See course site for due dateGeneral Instructions You will work individually on this the project.The code for this assignment should be developed and tested in a UNIX-basedenvironment. You can use the VM that has been made available to you for ECE551.You must follow this assignment specs carefully, and turn in everything that is asked(and in the proper formats, as described).You should plan to start early on this project and make steady progress over time. It willtake time and careful though to work through the assignment.Implementation of malloc libraryFor this assignment, you will implement your own version of several memory allocationfunctions from the C standard library (actually you will have the chance to implement and studyseveral different versions as described below). Your implementation is to be done in C code.The C standard library includes 4 malloc-related library functions: malloc(), free(),calloc(), and realloc(). In this assignment, you only need to implement versions ofmalloc() and free(): void * malloc(size_t size); void free(void *ptr);Please refer to the man pages for full descriptions of the expected operation for thesefunctions. Essentially, malloc() takes in a size (number of bytes) for a memory allocation,locates an address in the program’s data region where there is enough space to fit the specifiednumber of bytes, and returns this address for use by the calling program. The free() functiontakes an address (that was returned by a previous malloc operation) and marks that dataregion as available again for use.The submission instructions at the end of this assignment description provide specific detailsabout what code files to create, what to name your new versions of the malloc functions, etc.As you work through implementing malloc() and free(), you will discover that as memoryallocations and deallocations happen, you will sometimes free a region of memory that isadjacent to other also free memory region(s). Your implementation is required to coalesce inthis situation by merging the adjacent free regions into a single free region of memory.Hint: For implementing malloc(), you should become familiar with the sbrk() system call.This system call is useful for: 1) returning the address that represents the current end of theprocesses data segment (called program break), and 2) growing the size of the processes datasegment by the amount specified by “increment”. void *sbrk(intptr_t increment);Hint: A common way to implement malloc() / free() and manage the memory space is tokeep an adequate data structure to represent a list of free memory regions. This collection offree memory ranges would change as malloc() and free() are called to allocate andrelease regions of memory in the process data segment. You may design and implement yourmalloc and free using structures and state tracking as you see best fit.In this assignment, you will develop a malloc implementation and study different allocationpolicies. Study of Memory Allocation PoliciesYour task is to implement 2 versions of malloc and free, each based on a different strategyfor determining the memory region to allocate. The two strategies are:First Fit: Examine the free space tracker (e.g. free list), and allocate an address fromthe first free region with enough space to fit the requested allocation size.Best Fit: Examine all of the free space information, and allocate an address from thefree region which has the smallest number of bytes greater than or equal to therequested allocation size.The following picture illustrates how each strategy would operate (assuming free regions aretraversed in a left to right order) for a malloc() request of 2 bytes:Requirements: Malloc implementationsTo implement your allocation strategies, you will create 4 functions://First Fit malloc/freevoid * ff_malloc(size_t size);void ff_free(void * ptr);//Best Fit malloc/freevoid * bf_malloc(size_t size);void bf_free(void * ptr);Note, that in all cases, a policy to minimize the size of the process’s data segment should beused. In other words, if there is no free space that fits an allocation request, then sbrk()should be used to create that space. However, you do not need to perform any type of garbagecollection (e.g. reducing the size of the process’s data segment, even if allocations at the top ofthe data segment have been freed).On free(), your implementation is required to merge the newly freed region with any currentlyfree adjacent regions. In other words, your bookkeeping data structure should not containmultiple adjacent free regions, as this would lead to poor region selection during malloc.Requirement: Performance study reportIn addition to implementing these malloc functions, you are tasked to conduct a performancestudy of the malloc()with different allocation policies. Several programs for experimentationwill be provided that perform malloc() and free() requests with different patterns (e.g.frequencies, sizes). The metrics of interest will be:1) the run-time of the programs, as the implementation of different allocation policies mayresult in different speeds of memory allocation;2) the memory fragmentation is a number in the interval [0,1] (interpreted as apercenbtage), which is measured as follows:−(size of largest allocatable memory block/total size of free memory)In order to capture #2, you should also implement two additional library functions:unsigned long get_largest_free_data_segment_size();//in bytesunsigned long get_total_free_size();//in bytesThen, using these functions, you can use the included test programs as well as test programs ofyour own creation to evaluate and compare the algorithms.The Starter KitA starter kit is included in a file on Sakai: homework1-kit.tgzThis archive can be extracted using “tar xvzf homework1-kit.tgz”.The kit includes: Makefile: A sample Makefile for libmymalloc.so. general_tests/: General correctness test, see README.txt for details. alloc_policy_tests/: Allocation policy test cases, see README.txt for details. alloc_policy_tests_osx/: Same thing adapted for MacOS.NOTE: Mac OS is not the grading platform; these files are provided as a convenience.Additionally, you may need to change #include "time.h" to #include "sys/time.h"Testing your systemCode is provided for minimal testing, but the provided materials will not exhaustively evaluatethe correctness of your implementation. It is recommended to create your own test software thatuses your library, both to aid during development and to ensure correctness in a variety ofsituations.Detailed Submission InstructionsPlease submit a written report called report.pdf to Sakai (a submission link will beposted soon). The report should include an overview of how you implemented theallocation policies, results from your performance experiments, and an analysis of theresults (e.g. why do you believe you observed the results that you did for differentpolicies with different malloc/free patterns, do you have recommendations for whichpolicy seems most effective, etc.).Please submit a zipped file hw1_netID.zip to Sakai (e.g., if the netID is abc123, thename of the file should be hw1_abc123.zip). All source code should be included in adirectory named “my_malloc”. There should be a header file name “my_malloc.h” with the function definitionsfor all _malloc() and _free() functions. You may implement these functions in “my_malloc.c”. If you would like to usedifferent C source files, please describe what those are in the report. There should be a “Makefile” which contains at least two targets: 1) “all” shouldbuild your code into a shared library named “libmymalloc.so”, and 2) “clean” should remove all files except for the source code files. The provided Makefilemay be used as-is, expanded upon, or replaced entirely. If you have notcompiled code into a shared library before, you should be able to find plenty ofinformation online. With this “Makefile” infrastructure, the test programs will beable to: 1) #include “my_malloc.h” and 2) link against libmymalloc.so (-lmymalloc), and then have access to the new malloc functions. Just like that, youwill have created your own version of the malloc routines in the C standardlibrary!

March 18, 2022 · 6 min · jiezi

关于c:CS139-C-项目

CS139 C Programming ProjectNovember 24, 2020The objective of this project is to practice the implementation of structures and functions in C.The submission of the project requires the source code and a readme.pdf describing it.Pokémon DatabasePart 1 - Structure (4 points)Implement a structure named pokemon, which contains the following elements id (int)name (char*)height (float)type (char*)It is suggested to use an array of the designed structure as the database, for example:struct pokemon pkdb[100]; orstruct pokemon *pkdb[100];However, other forms such as linked list are also acceptable.Part 2 - Basic Functions (4 points)The following functions should be realized.int insert(int id, char name, float height, char type);Add a new pokemon into the database. Return 0 if successful. Return 1 if the max size of thedatabase is exceeded.int delete_id(int id);Delete the pokemon of given id from the database. Return 0 if successful. Return 1 if thepokemon of given id doesn’t exist in the database.Then print a sentence to describe the situation according to the return value.Part 3 - Extended Functions (8 points)The following functions should be realized.void find_height(int param);param ∈ {1, 2}. Find the pokemons with maximum height (param=1) or minimum height1(param=2). Print the name of the found pokemons.Make sure to print all the pokemons if they have the same maximum or minimum height.void sort_id(); Sort the database with id-ascending order. Print all pokemon names in order.void sort_id_plus(int param);param ∈ {1, 2}. Sort the database with id-ascending order (param=1) or id-descending order(param=2). Print all pokemon names in order.Use pointer to function (such as the functions below) instead of duplicating the sort process.int ascending (int a, int b) { return b<a; }int descending (int a, int b) { return b>a; }void group(char* type);Print the name of all the pokemons belonging to the given type.Part 4 - Free Design (4 points)Design and implement a feature for the database. Feel free to add any element in the structure andadd any function. Explain this feature in detail in readme file.For example, it could be a great idea to implement the evolutionary chains of pokemons. For pokemonEevee, the function could find its evolution Vaporeon, etc.Input and OutputThe main function firstly reads the information of several pokemons, then reads a set of instructionsand prints corresponding output.The first line of input is an integer n ≤ 50, indicating the number of pokemons in the following lines.For each pokemon, there are 4 lines containing its id, name, height and type respectively. Remarkthat each pokemon may have at least 1 type and at most 2 types. Types are separated with a singlecomma.Then there’s an integer m ≤ 20, indicating the number of instructions. Each line contains 1 instruction,which is consisted of a number and a parameter, separated by a blank. The number is theenumeration of corresponding function: 2 delete_id, 3 find_height, 4 sort_id, 5 sort_id_plus, 6 group.The parameter is passed into the function as argument.There’s a sample of input and output in the appendix. Each instruction and its output is aligned. Itcould be used to validate the functions.Remark that the format of the output is not important. Do not bother with order of print (exceptfor sort_id or sort_id_plus), or number of blanks.Charmander Charizard Pikachu Nidoran LaprasLaprasPikachu NidoranDeleted successfully !Pokemon of id 29 doesn’t exist in the database.Charmander Charizard Pikachu LaprasLapras Pikachu Charizard CharmanderCharizard CharmanderLapras

March 13, 2022 · 3 min · jiezi

关于c:RBE104TC-开发

RBE104TC C/C++ Programming LanguageAssignment 1Assignment Overview:This assignment aims at testing some basic concepts of the C programming andinitiates the routine of code development using the software development process(SDP) presented in the relevant lectures. It focuses on the following five steps ofthe SDP. Problem statement: formulate the problem;Analysis: determine the inputs, outputs, variables, etc.;Design: define the list of steps (the algorithm) needed to solve theproblem;Implementation: the C code has to be submitted as a separate file, justindicate here the name of the file;Testing: explain how you have tested and verified your C program.You will need to apply this methodology to each one of the following simpleexercises.Things to note:Include clear comments in your code to make it easy to understand.Explain your testing procedure and what you have observed during thetesting. The testing should be demonstrated by screenshot pictures topresent the actual implementation output.How you solved any problems.Contribution to the Overall Marks 40%Issue DateSubmission Deadline Dec. 21st, 2020/ 5Exercise 1 (25%):Write a C program that can perform the following operations:• Read the following from the keyboard and store them in appropriate variables;• A full name (e.g. John Smith);• A telephone number (e.g. 12345678900) assume all phone numbers are withdigits;• A 2 digit decimal number (e.g. 22);• A temperature in degrees Celsius (e.g. 28.5°C).• Divide the first 6 figures of the telephone number by the last 5 and store theresult in a variable. Print the value on the screen (e.g. 123456/78900 = 1.56;• Print an integer on the screen with the decimal, the octal, and the hexadecimalformat (e.g. 45, 55,2D);• Convert the temperature from degrees Celsius to degrees Fahrenheit anddegrees Kelvin. Store the values in appropriate variables rounded to theclosest whole number and print them on the screen (e.g. 10°C 50°F 283°K);• Solve the real roots of the quadratic equation for any real input a,b,c (e.g.invalid(a = 0), two equal real roots, two unequal real roots, or no real roots).Exercise 2 (30%):• Write a functionbool same_vec (vector<int> a, vector<int> b)that checks whether two vectors are including the same elements, ignoringthe order and multiplicities.• For example, the two vectors {1, 4, 9, 16, 9, 7, 4, 9, 11} and {11, 11, 7, 9, 16, 4, 1}would be considered identical.Requirements:Get the numbers from keyboard input;The length of the vectors is unknown, it is only determined by the input./ 5Exercise 3 (45%):An entertainment company designs a game: both the player and the computergenerate a letter taking the value A, B, C, but the result is determined by thefollowing rules: A < B, B < C, and C < A. It would now invite you to develop thissoftware to provide players of the game with their own secured account in whichtheir game history including the win, lose, or draw numbers is recorded and storedin a file. There are several requirements as described in the following section.Program Requirements• Your program should provide users with the ability to create an account. Anaccount should be a structure type variable containing: a username, a password,and a record of the game history.• The game history should be stored in a two-dimensional array and contain thefollowing details as a minimum:i. Number of rounds in a gameii. Number of player winsiii. Number of computer winsiv. Number of drawsv. Whether or not the game was overall a winning, draw or loss.• All of the accounts should be stored in a data file and accessed by the program.• Once a user is logged on to the game they should be able to:i. Start a new gameii. Review their game historyiii. Clear their game historyiv. Logout• Normally, the use of global variables is not allowed. Any use of global variablesmust be fully justified in your report.Ideas:Note: the following are only to provide you with ideas of how to implement therequired functionality. They do not represent the “best” or only ways to implementthe functions.All of the player accounts are structure variables and will be stored in a file. Thelogin process can be achieved using a single structure variable, into which eachaccount can be read from the file one by one, each time checking the usernameuntil you find the correct players' account. The gaming operations can then beperformed using that single structure variable. When the player finishes only thisone structure needs to be written back to the file for saving.Alternatively, you can create an array of structures in the program and read thewhole file into the array, then search the array. The game can be played using the/ 5correct element of the array of structures. When the player finishes, the whole arraycan be written to the file.Try to create your own functions to simplify the programming task.Consider how your program should function when there is an invalid input.To make your program more interesting for the user thinks about what kind ofinformation they may like to access for example overall win percentages./ 5What should be submitted?You should submit the followings:1). A short report (up to a few pages of text plus C source codes) detailing for eachquestion:a). SDP steps 1 to 3 in the report (Report + Specification + Analysis +Algorithm Design) (40%);b). SDP step 4 (Implementation + Robustness): your C source code includingthe comments. (40%);c). SDP step 5 (testing): you will explain how you have tested the correctnessof your C program and will include some sample runs of your C Programs.(20%);Please refer to the file Marking Guidelines for RBE104TC.pdf on the Learning Mallsystem for a detailed marking scheme.2). The report in Microsoft Word or pdf format and C source code of yourimplementation zipped into a single file, i.e. the zip file will contain 2 files. (It is goodpractice to include comments in your code see the example provided.)The naming of Report ( .doc, .docx or .pdf only), Source Code (.c) and Compressedfile (.zip, or .rar only)StudentID_LastName_FirstName_AssignmentNumber.docStudentID_ AssignmentNumber.cStudentID_LastName_FirstName_AssignmentNumber.zipFor example:Report and c source file named:1234567_Albert_Einstein_1.doc1234567_1.cContained within the zip file:1234567_Albert_Einstein_1.zipHow the work should be submitted?Should be submitted electronically through the Learning Mall system so that themarker can run your programs during marking. Feedback and your grade will alsobe given through the Learning Mall system.

March 11, 2022 · 5 min · jiezi

关于c:C语言编程程序的内存如何布局

 一:C语言程序的存储区域 由C语言代码(文本文件)造成可执行程序(二进制文件),须要通过编译-汇编-连贯三个阶段。编译过程把C语言文本文件生成汇编程序,汇编过程把汇编程序造成二进制机器代码,连贯过程则将各个源文件生成的二进制机器代码文件组合成一个文件。 C语言编写的程序通过编译-连贯后,将造成一个对立文件,它由几个局部组成。在程序运行时又会产生其余几个局部,各个局部代表了不同的存储区域: 1.代码段(Code或Text) 代码段由程序中执行的机器代码组成。在C语言中,程序语句进行编译后,造成机器代码。在执行程序的过程中,CPU的程序计数器指向代码段的每一条机器代码,并由处理器顺次运行。 2.只读数据段(RO data) 只读数据段是程序应用的一些不会被更改的数据,应用这些数据的形式相似查表式的操作,因为这些变量不须要更改,因而只须要搁置在只读存储器中即可。 3.已初始化读写数据段(RW data) 已初始化数据是在程序中申明,并且具备初值的变量,这些变量须要占用存储器的空间,在程序执行时它们须要位于可读写的内存区域内,并具备初值,以供程序运行时读写。 4.未初始化数据段(BSS) 未初始化数据是在程序中申明,然而没有初始化的变量,这些变量在程序运行之前不须要占用存储器的空间。 5.堆(heap) 堆内存只在程序运行时呈现,个别由程序员调配和开释。在具备操作系统的状况下,如果程序没有开释,操作系统可能在程序(例如一个过程)完结后回收内存。 6.栈(stack) 栈内存只在程序运行时呈现,在函数外部应用的变量、函数的参数以及返回值将应用栈空间,栈空间由编译器主动调配和开释。 C语言指标文件的内存布局 看一个例子: int a = 0; //全局初始化区,。data段 static int b=20; //全局初始化区,。data段 char *p1; //全局未初始化区 .bss段 const int A = 10; //.rodata段 void main(void) { int b; //栈 char s[] = "abc"; //栈 ...

March 6, 2022 · 2 min · jiezi

关于c:COMP1711XJCO1711-解析

University of Leeds School of ComputingProcedural Programming COMP1711/XJCO1711Semester 1, 2020-2021Coursework 3100 Marks (40% of the total module mark)To be submitted before: 23:00 (UK time) on 11 December 2020Late penalties: 5% will be deducted from the overall mark of this coursework for everylate daySkills TestedThis coursework will test your ability to write C code that correctly uses structures, character strings,pointers, and file i/o. You will also learn how a program can be divided across multiple source files.The BriefYou will write a program that allows people to name pairs of stars in a hypothetical universe by theirnames.The DetailsAn astronomer wanted to surprise their spouse on their anniversary by showing them a simulation ofthe Big Bang on a computer, then naming the closest pair of stars created by this Big Bang with theirnames. Big Bang is the name of a cosmological theory that assumes that the universe started from theexpansion of a single very high-density singularity.Fortunately, the program is not supposed to go anywhere close to a real simulation of the Big Bang.For the purposes of this simple program, our Big Bang simply fills a flat rectangular space with starsscattered at random positions. The program then allows a user to find the closest pair of unnamedstars in this universe and assign the user’s name to the first star in this pair, and the name of the user’sspouse to the second star.The TaskWrite a command driven program that accepts the following commands:The bang commandThis command creates a hypothetical universe comprised of stars only. The stars should be randomlyscattered across the universe.We are assuming that the universe is flat and rectangular and is 60 light years long and 30 light yearswide. A light year is a unit of measure of distance and is equal to the distance that light can travel inone year (5.879x1012 miles). Do not get daunted by this jargon, just assume that your space is arectangle 60 units long and 30 units wide.The bang command takes one integer argument representing the number of stars to be created. Forexample, if the player types: ...

March 5, 2022 · 9 min · jiezi

关于c:C语言字符串处理函数

C语言提供了丰盛的字符串处理函数,能够对字符串进行输出、输入、合并、批改、比拟、转换、复制、搜寻等操作,应用这些现成的函数能够大大加重咱们的编程累赘。 用于输入输出的字符串函数,例如printf、puts、scanf、gets等,应用时要蕴含头文件stdio.h,而应用其它字符串函数要蕴含头文件string.h。 string.h是一个专门用来解决字符串的头文件,它蕴含了很多字符串处理函数,解说几个罕用的。 字符串连贯函数 strcat() strcat 是 string catenate 的缩写,意思是把两个字符串拼接在一起,语法格局为: strcat(arrayName1, arrayName2); arrayName1、arrayName2 为须要拼接的字符串。 strcat() 将把 arrayName2 连贯到 arrayName1 前面,并删除原来 arrayName1 最初的完结标记'\0'。这意味着,arrayName1 必须足够长,要可能同时包容 arrayName1 和 arrayName2,否则会越界(超出范围)。 strcat() 的返回值为 arrayName1 的地址。 字符串复制函数 strcpy() strcpy 是 string copy 的缩写,意思是字符串复制,也行将字符串从一个中央复制到另外一个中央,语法格局为: strcpy(arrayName1, arrayName2); strcpy() 会把 arrayName2 中的字符串拷贝到 arrayName1 中,字符串完结标记'\0'也一起拷贝。 strcpy() 要求 arrayName1 要有足够的长度,否则不能全副装入所拷贝的字符串。 字符串比拟函数 strcmp() strcmp 是 string compare 的缩写,意思是字符串比拟,语法格局为: strcmp(arrayName1, arrayName2); arrayName1 和 arrayName2 是须要比拟的两个字符串。 字符自身没有大小之分,strcmp() 以各个字符对应的 ASCII 码值进行比拟。strcmp() 从两个字符串的第 0 个字符开始比拟,如果它们相等,就持续比拟下一个字符,直到遇见不同的字符,或者到字符串的开端。 ...

March 4, 2022 · 1 min · jiezi

关于c:C语言形参和实参的区别

C语言函数的参数会呈现在两个中央,别离是函数定义处和函数调用处,这两个中央的参数是有区别的。 形参(形式参数)在函数定义中呈现的参数能够看做是一个占位符,它没有数据,只能等到函数被调用时接管传递进来的数据,所以称为形式参数,简称形参。 实参(理论参数)函数被调用时给出的参数蕴含了实实在在的数据,会被函数外部的代码应用,所以称为理论参数,简称实参。 形参和实参的性能是传递数据,产生函数调用时,实参的值会传递给形参。形参和实参的区别和分割 1) 形参变量只有在函数被调用时才会分配内存,调用完结后,立即开释内存,所以形参变量只有在函数外部无效,不能在函数内部应用。 2) 实参能够是常量、变量、表达式、函数等,无论实参是何种类型的数据,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参,所以应该提前用赋值、输出等方法使实参取得确定值。 3) 实参和形参在数量上、类型上、程序上必须严格统一,否则会产生“类型不匹配”的谬误。当然,如果可能进行主动类型转换,或者进行了强制类型转换,那么实参类型也能够不同于形参类型。 4) 函数调用中产生的数据传递是单向的,只能把实参的值传递给形参,而不能把形参的值反向地传递给实参;换句话说,一旦实现数据的传递,实参和形参就再也没有瓜葛了,所以,在函数调用过程中,形参的值产生扭转并不会影响实参。

March 4, 2022 · 1 min · jiezi

关于c:62-不同路径

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右挪动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 问总共有多少条不同的门路? 示例 1:输出:m = 3, n = 7输入:28 示例 2:输出:m = 3, n = 2输入:3解释:从左上角开始,总共有 3 条门路能够达到右下角。 向右 -> 向下 -> 向下向下 -> 向下 -> 向右向下 -> 向右 -> 向下示例 3:输出:m = 7, n = 3输入:28 示例 4:输出:m = 3, n = 3输入:6 提醒:1 <= m, n <= 100题目数据保障答案小于等于 2 * 109 解决办法1:递归遍历通过递归,列出所有可能性,递归进行条件为机器人走到边界或走到起点,如果是起点,total+1 void move(int curX,int curY,int m, int n,int *total) { if (curX < n - 1) { move(curX + 1, curY, m, n,total); } if (curY < m - 1) { move(curX, curY + 1, m, n,total); } if (curX == n - 1 && curY == m - 1) { *total = *total + 1; }}int uniquePaths(int m, int n) { int total = 0; move(0, 0, m, n,&total); printf("%d\n", total); return total;}解决办法2.每列求门路可能性 ...

March 3, 2022 · 2 min · jiezi

关于c:会计培训网站搭建免费开源net源码

举荐一个会计培训零碎,能够看视频,刷题,考试。试题能够间接excel批量导入,领取接口是支付宝和微信领取,后盾能够本人配置,已测能购买课程。直播性能还没有测试,有须要的能够本人下载测试,总体性能还是很欠缺的,现有的性能曾经能满足应用了,有想做二次开发的也能够下载源代码,本人批改,五星举荐。 1、选课核心:视频,课件,图文,付费课程都可自定义增减,防录屏2、直播版块:屏幕共享,电子白板,文字交换,千人在线晦涩直播3、模仿考场:试题批量导入导出,多种形式模仿练习4、学习记录:可查问追溯,禁止后盾播放,准确统计学习进度,打印学习证实5、考务核心:无纸化在线考试,千人同考,强制交卷,防舞弊,批量导出问题6、营销引流性能:积分,优惠券,学习卡,三级分销7、在线领取:对接支付宝,微信领取,主动开课8、后盾治理:对平台学员的增、删、改、查,反对分组和 excel 批量导入导出 运行环境:服务器操作系统:windows server 2012 64位中文版数据库:Microsoft SQL Server 2008.NET版本:.NET4.6 开发环境:采纳C#;基于.Net 4.6 数据库采纳Sqlserver2008或更高版本开发工具 Microsoft Visual Studio Community 2019 下载:https://pan.baidu.com/s/1koQy... 提取码:xekq源码:https://gitee.com/weishakeji/...或者源码技术十483828432备注“须要源码”开发交换kiu峮:10237400 留神:零碎装置后用记事本关上db.config文件里配置以下主域用域名拜访:例如拜访域名是:www.weisha100.net,主域处填写:weisha100.net,示例如下:add name="weisha100.net" 内网以及应用ip拜访:间接填写ip地址,示例如下:add name="122.114.68.70"留神:不须要带端口号。

March 3, 2022 · 1 min · jiezi

关于c:ifndef作用

最次要的作用:1、避免头文件的反复蕴含和编译;上面是谬误示范: headfile_1.h 1 #include <iostream> 2 class CTest_1 { 3 CTest_1() { 4 //do something,eg:init; 5 } 6 ~CTest_1() { 7 //do something ,eg:free; 8 } 9 void PrintScreen()10 {11 std::cout << "this is Class CTest_1!" << std::endl;12 }13 };headfile_2.h 1 #include "headfile_1.h" 2 class CTest_2 { 3 CTest_2() { 4 //do something,eg:init; 5 } 6 ~CTest_2() { 7 //do something,eg:free; 8 } 9 void PrintScreen()10 {11 std::cout << "this is Class CTest_2!" << std::endl;12 }13 };sourcefile.cpp ...

March 2, 2022 · 1 min · jiezi

关于c:旋转链表

给你一个链表的头节点 head ,旋转链表,将链表每个节点向右挪动 k 个地位。 示例 1: 输出:head = [1,2,3,4,5], k = 2输入:[4,5,1,2,3] 示例 2: 输出:head = [0,1,2], k = 4输入:[2,0,1] 提醒:链表中节点的数目在范畴 [0, 500] 内-100 <= Node.val <= 1000 <= k <= 2 * 109 思路:将k对链表长度(后记为len)取模,如果k与len相等,则k = len,再进行旋转(余数为多少就旋转多少次)。 获取链表长度(帮忙函数): int length(struct ListNode* p) { struct ListNode* q = p; int length = 0; while (q != NULL) { length++; q = q->next; } return length;}单次旋转: void rotate(struct ListNode **p) { struct ListNode* q = *p; struct ListNode *secondToLast = *p; while (q != NULL) { if (q->next != NULL) { secondToLast = q; } q = q->next; } secondToLast->next->next = *p; *p = secondToLast->next; secondToLast->next = NULL;}struct ListNode* rotateRight(struct ListNode* head, int k) { int len = length(head); if (len == 0 || len == 1) return head; int _k; if (k % len == 0) { _k = len; } else { _k = k % len; } for (int i = 0; i < _k; i++) { rotate(&head); } return head;}

March 2, 2022 · 1 min · jiezi

关于c:为什么INLINE-一般要加static

为什么__INLINE 个别要加static起因如下:开发者决定不了一个函数是否被内联,开发者只有建议权,只有编译器具备决定权。上面,咱们来看看一个被static inline润饰的非内联函数: static __inline int Fake_StaticInline_Add(int n1,int n2,int n3,int n4,int n5){ /只是为了多凑几条指令/ n1++;n1++;n1++;n1++;n1++;n1++;n1++;n1++;n1++;n1++;n1++;return (n1+n2+n3+n4+n5);;}这个函数咱们把他放在main.c中,并在main函数这样调用:i = Fake_StaticInline_Add(6,6,6,6,6);。当初咱们来看看他的反汇编代码: MOVS r0,#5 MOV r3,r0 MOV r2,r0 MOV r1,r0 STR r0,[sp,#0] BL Fake_StaticInline_Add MOV r4,r0 NOP惊不惊喜,意不意外? 这个函数竟然是被调用了的,而并没有被内联到调用它的中央。那么,为什么这个函数没变成内联函数呢?我推断是因为我在这个函数中写入了太多指令,编译器判断如果它变成内联函数,会极大占用空间,所以不将它编译成内联函数。但你还记得咱们之前把Inline_Add函数放在哪里吗?放在了一个头文件。试想,如果这个Inline_Add在没有被编译成内联函数的状况下,被include到了多个源文件中,势必会产生函数反复定义的问题。 因而,咱们要再加一个关键字static,能力防止这个问题。

March 2, 2022 · 1 min · jiezi

关于c:CSE240-实现链表

CSE240 – Introduction to Programming Language 1 | PageHomework 07CSE 240 Spring 2021 Homework 7:Linked List of Containers (50 points)Due Saturday, March 13, 2021 at 11:59PM, plus a 24-Hour grace periodIntroductionThe aim of this assignment is to make sure that you understand and are familiar with theconcepts covered in the lectures, including linked list, pointer operations, and parameterpassing mechanisms. This two-assignment combination allows you to put all together that youhave learned in C programming language into a large program. By the end of the assignment,you should have understood and exercised● Pointer and pointer to pointer operations accessing structured data● Linked list of structures, with complex manipulations of pointer and structure● Different types of parameter passing mechanisms and return values of different types.● Solving problems in recursionReading: Textbook Chapter 2, Section 2.5.4 on linked list and Section 2.6 on parameter passingand Section 2.10.Preparation: Complete the multiple choice questions in the textbook exercise section. Theanswer keys can be found in the course Web site. These exercises can help you prepare for yourweekly quiz and the exam. You are encouraged to read the other exercise questions and makesure you understand these questions in the textbook exercise section, which can help youbetter understand what materials are expected to understand after the lectures and homeworkon each chapter.You are expected to do the majority of the assignment outside of class meetings. Should youneed assistance, or have questions about the assignment, please contact the instructor or TAduring their office hours.You are encouraged to ask and answer questions on the course discussion board. However, donot share your answers and code in the course discussion board.Homework DescriptionThe following figure shows an instance of the linked list that you will be building and managingin these two homeworks. The node of the main linked list ‘list’ is called libraryList, whichcontains two members: (1) book member is a pointer to the book node, (2) a pointer to nextlibraryList node. The book node contains three members: (1) book title, (2) aisle number, and(3) a pointer to bookType list. The node in the bookType list has two members: (1) book type (2)a pointer to next bookType node.CSE240 – Introduction to Programming Language 2 | PageHomework 07 libraryListHW 7 Programming Assignment (50 points)You are given a partially completed program hw7.c. You should follow the instructions given inthe program to complete the functions so that the program executes properly. You will becompleting a program that creates a list of books. It is a menu driven program where user isgiven following options:a) Add an book’s information (Book title and aisle number) is already implemented. Thenew book is added to the head of the linked list. We do not ask user for bookTypes toadd in this function. So simply NULL is assigned to *bookType member of the ‘book‘node when a new book is added to the list in this function. (Note: *bookType is used infurther functions)b) Display the book list is already implemented. This function prints each book’s title andaisle number. It does not print bookType of the book.These functions need to be implemented:c) Search a book in the list by book title. It prints if the book exists on the list or not. Thisfunction should return the ‘book‘ node if that book is found in the list, else return NULL.It is used as a helper function in executeAction() to check if the book exists in the list.The next part focuses on using ‘bookType’ linked list. In this part, the user should be able to usethe following menu options:a) Add a bookType to an book’s profile. This function assumes that the book is added inthe list and assigns book type using the *bookType member of ‘book’ node. You mayadd the new bookType to the head or tail of the ‘bookType’ linked list. (Sample solutionadds the bookType to the tail)list book*next*book*next*book*nextBook titleaisle*bookTypeBook titleaisle*bookTypeBook titleaisle*bookTypetype*nexttype*nexttype*nextnullnullnul null lbookbookTypeCSE240 – Introduction to Programming Language 3 | PageHomework 07b) This function prompts the user to input a book type. Then it displays the list of booksthat have the entered book type only. Lastly, it should display the number of books thatmet this requirement. This function should display both book’s title and aisle number.See expected output below.c) Removes the book from the list. This function removes the book’s title, aisle numberand bookType list of the book when removing the book from the list.Expected outputs:addBook (already implemented)CSE240 – Introduction to Programming Language 4 | PageHomework 07displayLibraryList (already implemenetd)(New books are added to the head of ‘list’. So newer books appear first. Not necessary to print‘end of list’ message.)searchBook (5 points)CSE240 – Introduction to Programming Language 5 | PageHomework 07addBookType (15 points)displayBookTypeList (15 points)( Sapiens recently added book type as ‘Nonfiction’ which was added to tail of her *bookTypelist. So, it’s name appears when ‘l’ option is used ).CSE240 – Introduction to Programming Language 6 | PageHomework 07removeBook (15 points)(After removing a book, you should use the display option to verify it functioned correctly)What to Submit?You are required to submit your solution in a compressed format (.zip). Make sure yourcompressed file is label correctly - lastname_firstname7.zip. (All lowercase, do not putanything else in the name like "hw7".)The compressed file MUST contain the following:hw7.c (completed code)No other files should be in the compressed folder.If multiple submissions are made, the most recent submission will be graded. even if theassignment is submitted late.Submission preparation notice: The assignment may consist of multiple files. You must copythese files into a single folder for canvas submission. To make sure that you have all the filesincluded in the zip file and they work after unzip operation, you must test them beforesubmission. You must also download your own submission from the canvas. Unzip the file on adifferent machine and test your assignment and see if you can open and test the files in adifferent location, because the TA will test your application on a different machine. If yousubmitted an empty project folder, an incomplete project folder, or a wrong folder, you cannotresubmit after the submission linked is closed! We grade only what you submitted in the canvas. CSE240 – Introduction to Programming Language 7 | PageHomework 07We cannot grade the assignment on your computer or any other storage, even if the modificationdate indicated that the files were created before the submission due dates. The canvas submissionmay take a few minutes. Be patient and wait for it to complete.Where to Submit?All submissions must be electronically submitted to the respected homework link in the courseweb page where you downloaded the assignment.Late submission deduction policy● No penalty for late submissions that are received within 24 hours after the deadline;● 10% grade deduction for every day it is late after the grace period;● No late submission after Tuesday at 11:59PM.Grading RubricsEach sub-question (programming tasks) has been assigned certain points. We will grade yourprograms following these steps:(1) Compile the code. If it does not compile, 50% of the points given for the code undercompilation will be deducted. Then, we will read the code and give points between 50%and 0, as shown in right part of the rubric table.(2) If the code passes the compilation, we will execute and test the code using test cases. Wewill assign points based on the left part of the rubric table.(3) In both cases (passing compilation and failed compilation), we will read your program andgive points based on the points allocated to each sub-question, the readability of your code(organization of the code and comments), logic, inclusion of the required functions, andcorrectness of the implementations of each function.(4) Please notice that we will not debug your program to figure out how big or how small theerror is. You may lose 50% of your points for a small error such missing a comma or aspace!(5) We will apply the following rubrics to each sub-question listed in the assignment. Assumethat points assigned to a sub-question is pts:Major Code passed compilation Code failed compilationPlease read the FAQ file in the Course Information folder:Q: For some reason, my assignment submission did not go through, but I thought it wentthrough. I can show you on my local disk or in my Dropbox that I completed the assignmentbefore the due date. Can my assignment be graded?A: You should always download your own submission from the blackboard after submission andtest if the submission contains all the required files. We will grade the assignment submitted toCanvas only. We cannot grade the assignment sent from email or stored in any other places,regardless its last-modified-time. If you submitted your assignment into the blackboard, it cannotbe downloaded from the instructor side, but it can download from your side, we can downloadfrom your blackboard and grade the assignment. Please meet the instructor or TA in this case. ...

February 24, 2022 · 7 min · jiezi

关于c:Permutation-Sequence

The set [1, 2, 3, ..., n] contains a total of n! unique permutations. By listing and labeling all of the permutations in order, we get the following sequence for n = 3: "123""132""213""231""312""321" Given n and k, return the kth permutation sequence. 思路:通过给定的n和k,一直的递加n,获取每一次的数组的索引值及k的新值,直到n为0,终止循环将获取的每一次的索引值,从数组(数据每一次取值后,都须要删除该值)内取出值即可。 int* copyIntList(int* list, int length) { int* result = (int*)malloc(length * sizeof(int)); for (int i = 0; i < length; i++) { result[i] = list[i]; } return result;}int getIndex(int n, int k) { return (double)ceil((double)k / getFabric(n - 1)) - 1;}int getFabric(int n) { if (n == 0) return 1; int total = 1; for (int i = 1; i <= n; i++) { total *= i; } return total;}void deleteElementByIndex(int* list, int length, int position) { for (int i = position; i < length; i++) { list[i - 1] = list[i]; }}char* getPermutationSequenceByIndex(int* list, int n, int k) { int _n = n, _k = k; int* _list = copyIntList(list, n); char* result = (char*)malloc((n + 1) * sizeof(char)); result[n] = '\0'; int curResultIndex = 0; while (_n > 0) { int curIndex = (int)getIndex(_n, _k); //dosomething 1.get index from list , then remove the index val of list; result[curResultIndex] = '0' + _list[curIndex]; curResultIndex++; deleteElementByIndex(_list, _n, curIndex + 1); int nextLen = getFabric(_n - 1); int nextK = _k % nextLen == 0 ? nextLen : _k % nextLen; _k = _k <= nextLen ? _k : nextK; _n--; } free(_list); return result;}char* getPermutation(int n, int k) { //生成int动静数组 int* p = (int*)malloc(n * sizeof(int)); for (int i = 0; i < n; i++) { p[i] = i + 1; } char* result = getPermutationSequenceByIndex(p, n, k); free(p); return result;}

February 24, 2022 · 2 min · jiezi

关于c:COMP282-重点解析

University of LiverpoolDepartment of Computer ScienceCOMP282 – Advanced Object-Oriented C LanguagesCoursework 1 – C++Deadline: Tuesday 13th April at 17:00Weighting: 50%Make sure your student ID is clearly shown in a comment at the top of your source code. Compress yourVisual Studio project into a single zip file and submit it via SAM. Penalties for late work will be applied inaccordance with the Code of Practice on Assessment.Project OverviewYou will create a small interactive program toinput details about people, manipulate them, anddisplay them. The project consists of severaltasks, which you should tackle in order. Each taskbuilds on the previous one. Do as much as youcan and then package your project forsubmission. Begin by downloading the VisualStudio project template for this assessment.Read through this entire document before youstart coding, so you’re aware of all tasks and theoverall structure of the program. Your solutionshould demonstrate your knowledge of C++.Important: Each task requires you to add extracode. You shouldn’t need to remove any code.Keep the code from previous tasks in yourprogram so we can see it and mark it.Important: Each part requires you to change thecode in the main() function, potentially losing theprevious version. Therefore we have providedfunctions called main_part1(), main_part2() andmain_part3(). Place your code for each partinside the relevant function. You can uncommentthe relevant lines in the real main() function torun and test each part.Part 1 (Worth 15%)Task 1 – Person Class Definition (5%)Create a Person class that stores a name and age. The name should be stored as a string, and the age as aninteger. Declare and define a constructor that takes appropriate parameters and stores them in the object.Also declare and define a default constructor that sets the name to an empty string and the age to zero.Task 2 – Person I/O (5%)Implement the << and >> operators so you can output and input a Person object with the following stringformat.Jasmine 18In other words, the name of the person is output followed by the age. When the user types a similar stringas input, the first token (up to the space) should be stored as the name, and the second (after the space) asthe age. For this task you do not need to do any input validation or error handling. Assume the user willalways type the correct format.Task 3 – Comparison Operators (5%)Implement comparison operators (<, >, and ==) for the Person class. These should work numerically, basedon the ages of the people involved.Add relevant test code to the main_part1() function. Make sure it’s sufficient to test all the implementedaspects of the Person class from all tasks so far.Part 2 (Worth 45%)Task 4 – Adding & Listing People (Fixed Storage) (20%)Implement this and subsequent tasks in the main_part2() function. Create a loop to present menu itemsand input user choices. At this stage the menu will only have three options. ...

February 24, 2022 · 6 min · jiezi

关于c:获取数组的全排列

依据给定的int型数组,给出全排列 比方:[1,2] => [[1,2],[2,1][1,2,3] =>[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] #include <stdio.h>#include <stdlib.h>int *concat(int* list, int length, int x) { int *result = (int*)malloc((length + 1) * sizeof(int)); for (int i = length; i > 0; i--) { result[i] = list[i - 1]; } result[0] = x; return result;}int getFactorial(int n) { int total = 1; for (int i = 1; i <= n; i++) { total *= i; } return total;}int** getPermutation(int * list ,int n) { int** result; int total = getFactorial(n); if (n == 2) { result = (int**)malloc(total * sizeof(int*)); for (int i = 0; i < total; i++) { result[i] = (int*)malloc(n * sizeof(int)); } result[0][0] = list[0]; result[0][1] = list[1]; result[1][0] = list[1]; result[1][1] = list[0]; return result; }else{ result = (int**)malloc(total * sizeof(int*)); for (int i = 0; i < n; i++) { int* tempList = (int*)malloc((n - 1) * sizeof(int)); int curIdx = 0; for (int j = 0; j < n; j++) { if (i == j) continue; tempList[curIdx] = list[j]; curIdx++; } int** tempResult = getPermutation(tempList, n - 1); int tempResultLength = getFactorial(n - 1); for (int k = 0; k < tempResultLength; k++) { result[tempResultLength * i + k] = concat(tempResult[k], n - 1, list[i]); } free(tempList); free(tempResult); } return result; }}int main() { int n =4; int* p = (int*)malloc(n * sizeof(int)); for (int i = 0; i < n; i++) { p[i] = i + 1; } int **result = getPermutation(p,n); for (int i = 0; i < getFactorial(n); i++) { for (int j = 0; j < n; j++) { printf("%d,", result[i][j]); } printf("\n"); } free(p); free(result); return 0;}

February 23, 2022 · 2 min · jiezi

关于c:CSCI-2100B数据结构

CSCI 2100B Data StructuresAssignment 2Due Date: 16 March 2021Written Exercises Write the following function that makes use of the listADT of list of integers:listADT moveMinToHead(listADT);which moves the minimum element in the list to the head of the list if the argumentlist is nonempty, or returns an empty list otherwise. For examples,• moveMinToHead([]) = []• moveMinToHead([3,4,8,2,4]) = [2,3,4,8,4]• moveMinToHead([3,5]) = [3,5]• moveMinToHead([7]) = [7]a) Write this function as a recursive function. Hint: Call moveMinToHead with the tailas the argument.b) Write this function as a nonrecursive function.Write the following function that sorts the argument list into ascending order byselection sort:listADT selectionSort(listADT);Hint: Make use of the moveMinToHead function.Use the selection sort algorithm to sort the following sequence of integers intoascending order:1, 8, 6, 6, 5, 7, 9Show clearly each step in the process of sorting.Write the following functions as recursive functions in C. You should use the listoperations defined in list ADT shown in the lecture notes. You can simply callexit(EXIT_FAILURE) when error conditions are encountered. Note that your functionsshould work well with any correct implementation of list ADT.a) The function listIsSorted that accepts a listADT argument and returns an int valueif the argument list is sorted, or 0 otherwise. For examples:§ listIsSorted([7,8,1,5,3]) = 0§ listIsSorted([4,5,6,7]) = 1§ listIsSorted([0]) = 1§ listIsSorted([]) = 1b) The function lastButOne that accepts a listADT argument and returns an int valuethat is the last-but-one value in the list. For examples:§ lastButOne([3,4,8,2,4]) = 2§ lastButOne([0,1]) = 0§ lastButOne([]) = ERROR§ lastButOne([4]) = ERRORc) The function member that accepts an int argument and a listADT argument, andreturns an int value true if the int argument is in the listADT argument, or 0otherwise. For examples:§ member(2, [3,4,8,2,4]) = 1§ member(4, [3,5]) = 0d) The function firstN that accepts a listADT argument and an int argument N, andreturns a listADT value that is the list of the first N elements of the argument, untilthe end of the list. For examples:§ firstN([3,4,8,2,4], 3) = [3,4,8]§ firstN([2,4,6], 8) = [2,4,6]§ firstN([], 0) = []§ firstN([], 1) = []§ firstN([8,7,6], 3) = [8,7,6]e) The function evenOnly that accepts an int argument and a listADT argument, andreturns a listADT result that is the same as the List argument, except that all theodd numbers are removed. For examples:§ evenOnly([3,4,8,2,4]) = [4, 8, 2, 4]§ evenOnly([3,5]) = []§ evenOnly([2,8,4]) = [2, 8, 4]§ evenOnly([]) = []f) The function listsAreDifferent that accepts two listADT arguments, and returns anint value 1 if the listADT arguments are different, or 0 otherwise. For examples:§ listsAreDifferent([], [3,4,8,2,4]) = 1§ listsAreDifferent([2], []) = 1§ listsAreDifferent([], []) = 0§ listsAreDifferent([39,3,8,12,3], [39,3,8,11,3]) = 1§ listsAreDifferent([39,3,8,12,3], [39,3,8,12,3]) = 0In the implementation version 2.0 of list ADT, we use a linked list-basedimplementation of lists. On page 13 of lecture notes LN6-2a, we show list1 and list2after a few statements are executed. For each of the code segments shown below,show the linked list-based implementation of lists list1, list2 and list3 after all thestatements in the code segment are executed (you should assume that list1, list2 andlist3 are all properly declared as listADT variables). You should also indicate what willbe outputted from each of the code segments that contain printf statements.a) list1 = Cons(4, Cons(5, Cons(6, EmptyList())));list2 = Cons(Head(list1), list1);b) list1 = Cons(3, Cons(7, Cons(6, EmptyList())));list2 = Cons(Head(list1), Tail(list1));list3 = Cons(0, list2);c) listElementT firstElement, secondElement;list1 = Cons(8, Cons(4, Cons(7, EmptyList())));firstElement = Head(list1);secondElement = Head(Tail(list1));list3 = Cons(secondElement, Tail(Tail(list1)));list2 = Cons(secondElement, Cons(firstElement, list3));d) if (listEqual(EmptyList(), EmptyList()))printf("listEqual(EmptyList(), EmptyList())\n");elseprintf("Not listEqual(EmptyList(), EmptyList())\n");if (EmptyList() == EmptyList())printf("EmptyList() == EmptyList()");elseprintf("EmptyList() != EmptyList()");e) list1 = Cons(8, Cons(4, Cons(7, EmptyList())));list3 = Tail(Tail(list1));list2 = Cons(Head(Tail(list1)), Cons(Head(list1), list3));Programming ExercisesThere are two parts in this programming exercise.a) (Part 1) In the lecture notes we have seen how to implement symbol tables usingHash tables. In the version we present in the lecture notes, we use the techniqueof separate chaining to resolve collisions. We shall call this version 1.0.Implement version 2.0 of symtabADT, in which you use quadratic probing (insteadof separate chaining) for collision resolution. You should use F(i)=iin yourimplementation. Also you should set the table size at 51. You should use thefollowing hash function.int Hash(char *s, int n) { unsigned long hashcode = 0UL; for (int i=0; s[i]!='\0'; i++) hashcode = (hashcode<<6) + (unsigned long) s[i]; return (int) (hashcode % n);}In your implementation, you should use the following definition for structsymtabCDT:typedef struct bucketT { int inUse; // This is 1 if the bucket is in use, or 0 otherwise char *key; void *value; } bucketT;struct symtabCDT { bucketT bucket[nBuckets]; };where nBuckets is constant 51 defined using #define in symtab.c.You shall need to implement at least four functions: EmptySymbolTable, Enter,Lookup, and ForEachEntryDo.Note: you only need to submit symtab.c that implements version 2.0 ofsymtabADT.b) (Part 2) Prof. Chan is teaching a course that is open to both postgraduate andundergraduate students. Prof. Chan decides to use different scales forpostgraduate and undergraduate students to convert from numeric marks togrades.The class list with marks of individual students is stored in a student data filestudentData.txt. The format of the student data file is shown as follows:218432CHAN TAI MAN78200987CHEUNG MAN MING90217748MAN TAI SUN75216639YEUNG WING KEUNG98A student’s information is stored in four separate lines in the student data file. Thefirst line is a 6-digit student number, the second line is the student’s name, andthe third line the student’s mark (which is an integer). Whether a student is apostgraduate student or an undergraduate student is indicated by his or herstudent number: if the second digit is 0, then the student is a postgraduate student;otherwise, the student is an undergraduate student. The total number of studentsis not known in advance, so you need to read the file until the end of file is reached.There is another file called the data correction file dataCorrection.txt. If there isany mistake in the studentData.txt file, then the correction information willappear in the data correction file for correction purpose. A student’s informationis stored in two separate lines in the data correction file. The first line is a 6-digitstudent number, and the second line the student’s correct mark (which is aninteger). We assume that there is only one data correction file for all teachers,that is, it might contain information about a student whose student number doesnot appear in the original student data file. This is because it is actually a correctionfor the student data file of another teacher. If this happens, the you can simplyignore it. The following is an example of the data correction file:In this case the student whose student number is 200100 does not appear in thedata file, so it can be ignored.Write a program that first reads the student data file and then the data correctionfile, and outputs the grades of each of the students in a file. The following is asample output for the above input file (the order is not important).CHAN TAI MANBCHEUNG MAN MINGAMAN TAI SUNBYEUNG WING KEUNGANote 1You must use the following implementation:You must first use typedef to define a structure type StudentT for a structurewith 3 fields.§ The first field sName is a string that stores the name of the student.§ The second field level is a value of type studentLevelT(studentLevelT level), where studentLevelT is an enum type definedastypedef enum {UG, PG} studentLevelT;§ The last field mark is an int value (int mark) that stores the student’sexamination mark.There is a function char getGrade(StudentT) to determine the grade foreach of the students.The conversion schemes for undergraduates and postgraduates are as follows:Undergraduate Postgraduate– 100 A 90 – 100 A– 86 B 75 – 89 B– 71 C 65 – 74 C– 58 D < 65 F< 50 FNote 2You should use a symbol table to store the students’ information in your program.The key is the student IDs. The data stored in the table should be pointers of typeStudentT*, which point to structures of type StudentT. For simplicity, you canassume that the table will never be full.Your program should work well using the symtab.h and symtab.c in the lecturenotes and in Part 1 of the question.Note 3To output the grades of all students, you must use a call back functionvoid displayStudentNameAndGrade(char, StudentT)to display all entries in the table (the order is not important). You may use themapping function forEachEntryDo defined in the lecture notes.

February 23, 2022 · 7 min · jiezi

关于c:蓝桥杯cPython每日练习每日刷题day9流浪的小灰灰数小灰分苹果

一,漂泊的小灰题目形容 小灰,是一只出世在逸夫楼(大略是吧╮(╯▽╰)╭)的老鼠。它从小就受到各个科技类社团的陶冶,精通c/c++等语言的编译器装置,精通Windows、Unix、linux等操作系统的开关机,是一只有文化的老鼠。它始终在逸夫楼到处游荡,寻找一个和煦的家。 有一天,他发现了ACM程序设计协会这个小家庭。在无数次目击过协会成员们舒适的日常生活后,小灰终于按捺不住心中的激动,决定退出ACM协会,成为一只ACMer(^o^/)。然而,退出协会是须要通过考试的,摆在小灰背后的是一道数学题,题目如下: 给出两个数字A和B,两个数字之间用”+”“-”“”“/”连贯,如果给出的是A+B,则计算(A-B)的值;如果给出的是A-B,则计算(A+B)的值;如给出的是A/B,则计算(AB)的值;如果给出的是A*B,则计算(A/B)的值。(你这是在难为我小灰(╯‵□′)╯︵┻━┻) 这道题对于小灰来说太过于麻烦,所以它找到了聪慧的你,请你帮帮它吧! 输出 输出数据仅有一行,蕴含一个形如A+B的式子。 输入 请你输入计算结果,不要蕴含多余的空格和换行。 样例输出 1+1样例输入 0提醒 题目保障输出数据为正整数且计算结果在int范畴内。 对于除法保障不会呈现除零谬误,运算后果间接保留整数局部即可。c++解法: #include<bits/stdc++.h>using namespace std;int main(){ char a[10000]; scanf("%s",a); int len,l=0; len=strlen(a); int flag1=0,flag2; for(int i=0;i<len;i++) { if(a[i]=='+'||a[i]=='-'||a[i]=='*'||a[i]=='/') { flag1=i; break; } } char b[10000]; for(int j=flag1+1;j<len;j++) { b[l]=a[j]; l++; } long long c,d; c=atoi(a); d=atoi(b); if(a[flag1]=='+') { cout<<c-d; } if(a[flag1]=='-') { cout<<c+d; } if(a[flag1]=='/') { cout<<c*d; } if(a[flag1]=='*') { cout<<c/d; } return 0;}心得:应用atoi函数。atoi()函数的性能:将字符串转换成整型数;atoi()会扫描参数nptr字符串,跳过后面的空格字符,直到遇上数字或正负号才开始做转换,而再遇到非数字或字符串时('\0')才完结转化,并将后果返回(返回转换后的整型数)。 二,灰数题目形容 小灰是一只灰鼠,灰鼠有一个灰数,灰数来自于灰鼠,灰鼠想求出灰数···…… 不要问我为什么这次不是小灰求算数题,你们总是让小灰做算数、剪树叶、拼拼图,小灰曾经累了,小灰不想做题,小灰只想做一只宁静的小灰鼠,然而你们想过小灰的的感触吗,没有!你们只想着让小灰做题·····……^o^/我没疯^o^/放开我……………(拖走ヽ(゜▽゜ )-C<(/;◇/~) ...

February 22, 2022 · 1 min · jiezi

关于c:线程间同步信号量控制Semaphore

上一篇生产者-消费者的例子是基于链表的,其空间能够动态分配,当初基于固定大小的环形队列重写这个程序,这次不再利用mutex而是semaphore来实现线程间同步!上一篇文章链接:https://segmentfault.com/a/11... 仍旧是生产者生产一个构造体串在链表的表头上,消费者从表头取走构造体,生产者未生产或生产的曾经被拿完,则消费者须要挂起期待. 1 #include <stdlib.h> 2 #include <pthread.h> 3 #include <stdio.h> 4 #include <semaphore.h> 5 6 #define NUM 5 7 int queue[NUM]; 8 sem_t blank_number, product_number; 9 10 void *producer(void *arg) 11 { 12 int p = 0; 13 while (1) { 14 sem_wait(&blank_number);//wait能够取得信号,使init初始化中semaphore值-1,如果减到0则挂起期待,胜利取 用后持续进行后续操作 15 queue[p] = rand() % 1000 + 1; 16 printf("Produce %d\n", queue[p]); 17 sem_post(&product_number);//能够开释上述操作所占用的资源并唤醒期待执行的下个线程,并且使semaphore的> 值+1 18 p = (p+1)%NUM;//循环队列+1 19 sleep(rand()%5); 20 } 21 } 22 23 void *consumer(void *arg) 24 { 25 int c = 0; 26 while (1) { 27 sem_wait(&product_number);//此时product线程的semophore值曾经从init中的0变1,故此处有1个资源可供wait应用,不会阻塞!取用后在此变回0,但能够执行 后续操作了。 28 //此处因为还有一个信号可供wait取用,胜利取用而后持续后续操作 29 printf("Consume %d\n", queue[c]); 30 queue[c] = 0;//取用过的队列值设为0,便于察看过程间是否同步(即是否consumer取了曾经取过的队列值:) 31 sem_post(&blank_number);//开释一个信号(此处开释的是wait后续操作所占用的线程信号)给blank_number并唤醒下一个阻塞或期待中的过程,semaphore+1 32 c = (c+1)%NUM; 33 sleep(rand()%5); 34 } 35 } 36 37 int main(int argc, char *argv[]) 38 { 39 pthread_t pid, cid; 40 41 sem_init(&blank_number, 0, NUM); 42 sem_init(&product_number, 0, 0); 43 pthread_create(&pid, NULL, producer, NULL); 44 pthread_create(&cid, NULL, consumer, NULL); 45 pthread_join(pid, NULL); 46 pthread_join(cid, NULL); 47 sem_destroy(&blank_number); 48 sem_destroy(&product_number); 49 return 0; 50 }linux环境下执行:gcc semaphore.c -o semaphore -lpthread ...

February 19, 2022 · 1 min · jiezi

关于c:COMP281-讲解

COMP281 2020-2021 – Assignment 2• In the following, you will find the problems that constitute Assignment 2. They will be also availableon the online judging (OJ) system available at https://student.csc.liv.ac.uk...• You need to write a C program (not C++ or C#) that solves each problem – it must read the input, asspecified in the problem description then print the solution to the given problem for that input.o Note that code is “correct” only if it correctly implements a solution to the problem statedin the assignment, not "if online judge accepts it".o That is, even if OJ accepts your code, it could be wrong. Read the problems carefully.• Input is read from the standard input, in the same way that you read input from the keyboard as shownin lectures (e.g., using scanf). Output is also printed to the standard output, as you have seen (e.g.,using printf).• When you are satisfied that your C programs work correctly, you must submit them through thedepartmental submission system.o Even if the program is not correct, still submit whatever you have! You can still earn points ifcertain parts of the code are done right.• You must also include a brief report describing your solutions to the problems. This should bemaximum two sides of A4 paper and should give a description of how each of your solutions works.This should include describing the algorithm used to reach the solution, describing your use of any Clanguage features (that were not discussed in lectures) and identifying any resources that you haveused to help you solve the problems.• This assignment is worth 50% of the total mark for COMP281.o Both problems are weighted equally.o For each problem, you can earn a total of 50 points§ 25 points for “Functionality and Correctness” awarded for programs that correctlysolve the problem for all test cases.§ 20 points for “Programming style, use of comments, indentation and identifiers”awarded depending on the style, comments and efficiency of the solution§ 5 points for the quality and depth of the accompanying reporto The final grade results from normalising the earned points to a scale of 100.o See separate “comp281-detailed-marking-guidelines.pdf” for more details.Submission Instructions• Create a folder, and name it using your Student ID and User ID, e.g. 201234567_sgpj6• In the folder, there should be 3 files:o 1 report file, in PDF format. Name it with your Student ID and User ID, e.g.201234567_sgpj6.pdfo 2 source code files. Name each using the Problem Number, e.g. 1006.c§ In your source code, include your Student Info and Problem Info, e.g.:/* ...

February 16, 2022 · 8 min · jiezi

关于c:分析COMP206-Advanced-Unix-Utils

School of Computer Science, McGill UniversityCOMP-206 Introduction to Software Systems, Winter 2021Mini Assignment 3: Advanced Unix UtilsDue Date March 10th, 18:00 ESTThis is an individual assignment. You need to solve these questions on your own. If you have questions,post them on Piazza, but do not post major parts of the assignment code. Though small partsof code are acceptable, we do not want you sharing your solutions (or large parts of them) on Piazza.If your question cannot be answered without sharing significant amounts of code, please make a privatequestion on Piazza or utilize TA/Instructors office hours. Late penalty is -15% per day. Even ifyou are late only by a few minutes it will be rounded up to a day. Maximum of 2 late days are allowed.You MUST use mimi.cs.mcgill.ca to create the solution to this assignment. You must not use yourMac command-line, Windows command-line, nor a Linux distro installed locally on your laptop. You can accessmimi.cs.mcgill.ca from your personal computer using ssh or putty and also transfer files to your computer usingfilezilla or scp as seen in class and in Lab A and mini assignment 1.All of your solutions must be composed of commands from the list provided at the end of thisassignment description and your scripts must be executable as is in mimi.For this assignment, you will have to turn in one shell script. Instructors/TAs upon their discretion may ask youto demonstrate/explain your solution. No points are awarded for commands that do not execute at all. (Commandsthat execute, but provide incorrect behavior/output will be given partial marks.) All questions are graded proportionally.This means that if 40% of the question is correct, you will receive 40% of the grade.Please read through the entire assignment before you start working on it. You can loose severalpoints for not following the instructions. There are also some helpful hints given at the end of this documentthat can be useful to you.Lab E provides some background help for this mini assignment.Total Points: 20Ex. 1 — Parsing sensor logs for analysis (20 Points)The output produced by specialized software applications often contain a mixture of diagnostic details as well asuseful data. By processing their log files, we can glean for various useful information. In this assignment, we willuse the advanced Unix utilities that we covered in class to analyze the output log files from a temperature sensorsmonitoring program.The log files that we will be using for this assignment is available under the directory hierarchy of/home/2013/jdsilv2/206/m3/sensorlogs. Please note that this directory may not be accessible through FileZilla,etc. It is primarily meant to be accessed from the Unix command line in mimi. These will also be the files that TAswill be using to test your scripts.The log files are generated by a program that reads five different temperature sensors, once every hour (24 readings ina given day) and records these readings. If it was unable to read a particular sensor, it will indicate the correspondingsensor’s reading as ERROR. Along with this, the program also logs various other information (such as rebooting sensors,etc.) which we are not concerned with.A sample output of one of these log files is given below. (truncated for brevity). You can deduce the message formatsfrom the log files given to you as part of this assignment. Please note that positive temperature readings do not havean explicit + sign associated with them. For simplicity, you can assume that the temperature values are limited inthe range of 100.00 to -100.00, inclusive.2021-02-01 00:02:07 sensor readouts -12.35 -11.90 -11.97 -11.05 -11.6512021-02-01 01:03:01 rebooting sensor 42021-02-01 01:03:02 sensor readouts -13.85 -11.90 -12.97 ERROR -11.652021-02-01 02:04:00 rebooting sensor 5...2021-02-01 18:03:57 rebooting sensor 22021-02-01 18:08:47 rebooting sensor 32021-02-01 18:12:00 sensor readouts -10.35 ERROR ERROR -7.05 -3.652021-02-01 19:04:22 sensor readouts -11.85 -7.40 -6.97 -7.55 -4.15...2021-02-01 23:00:39 sensor readouts -12.85 -10.90 -7.47 -10.55 -8.65You will be writing a shell script dataformatter.sh that would process these log files. ...

February 15, 2022 · 11 min · jiezi

关于c:COM-S-352-Shell-Project

Project 1: 352> ShellCOM S 352 Spring 2021 IntroductionThis project consists of designing a C program to serve as a shell interface that accepts usercommands and then executes each command in a separate process. Your implementation willsupport input and output redirection, pipes, and background processes. Completing this projectwill involve using the Linux fork(), exec(), wait(), waitpid(), pipe() and dup2()system calls. It must be tested on pyrite.Main LoopIn its normal mode of operation, the shell prompts the user, after which the next command isentered. In the example below, the prompt is 352> and the user's next command is cat -nprog.c.352> cat -n prog.cThe command is executed while the shell waits for it to complete, after completion the shellprompts the user for the next command. Following the UNIX philosophy, most commands areseparate utility programs distributed along with the OS, there are only a few built-incommands: exit, jobs and bg. The purpose of exit should be clear, jobs and bg aredescribed in Section 7.Most of the main loop is provided for you in the starter code in Section 9.Basic CommandsA basic command consists of the name of an executable file, followed by zero or more spaceseparated arguments. The input and parsing of the command line is performed for you in thestarter code. Parsing populates an instance of the Cmd struct. For example, calling the parserwith the argument cmd having the field cmd->line of "cat -n prog.c" results in thefollowing assignments (note that the character \0 in a string literal means NULL).cmd->line = "cat -n prog.c";cmd->tokenLine = "cat\0-n\0prog.c";cmd->args = {pointer_to_c, pointer_to_minus_sign, pointer_to_p, NULL…};cmd->symbols = {NULL, NULL, NULL, NULL…};Commands should be run in a separate child process. Basic commands must be executed in theforeground, this means the shell is blocked (waiting) until the child process terminates. Thechild process is created using the fork() system call, the user's command is executed using one of the system calls in the exec() family and the shell waits for the command to completeusing one of the system calls in the wait() family. Get started by writing a function to executea command and call it from main() at the location indicated by the line:/ TODO: Run command in foreground. /File RedirectionYour shell should be modified to support the ‘>’ and ‘<’ redirection operators, where ‘>’redirects the output of a command to a file and ‘<’ redirects the input to a command from afile. For example, if a user enters352> ls > out.txtthe output from the ls command will be redirected to the file out.txt. Similarly, input canbe redirected as well. For example, if the user enters352> sort < in.txtthe file in.txt will serve as input to the sort command.The parser recognizes ‘<’ and ‘>’ as special symbols, for example, calling the parser with theargument cmd having the field cmd->line of "sort < in.txt" results in the following.cmd->line = "sort < in.txt";cmd->tokenLine = "sort\0<\0in.txt";cmd->args = {pointer_to_s, NULL, pointer_to_i, NULL…};cmd->symbols = {NULL, pointer_to_lt, NULL, NULL…};Simplifying Assumption: You can assume that commands will contain either one input or oneoutput redirection and will not contain both. In other words, you do not have to be concernedwith command sequences such as sort < in.txt > out.txt.PipesYour shell should be modified to support the ‘|’ pipe operator, which connects the stdoutof one process to the stdin of another.352> ls | grep txtThe output from the ls command will be piped to the utility grep.Managing the redirection of both input and output will involve using the dup2() function,which duplicates an existing file descriptor to another file descriptor. For example, if fd is a filedescriptor to the file out.txt, the calldup2(fd, STDOUT_FILENO);duplicates fd to standard output (the terminal). This means that any writes to standard outputwill in fact be sent to the out.txt file.Simplifying Assumption: You can assume that commands will contain no more than one pipe.In other words, you do not have to be concerned with command sequences such asls | grep txt | wc -l.Background CommandsThe use of an ampersand (&) at the end of a line indicates that the command should beexecuted in the background. The shell does not wait for background commands to complete, itimmediately prompts the user for the next command. However, the shell is expected tomonitor the status of background commands, in order to inform the user when a commandcompletes. Helper functions should be created and called from main() to start a command andcheck if a command is completed at the following TODO lines./ TODO: Run command in background. // TODO: Check on status of background processes. /When a background command is started the shell assigns it a number (starting at 1) anddisplays the pid of the process. When the process exits normally the shell displays themessage Done commandArgs as shown in the following example.352> ls -la &[1] 84653-rw-r--r-- 1 user group 100 Aug 28 03:22 file1-rw-r--r-- 1 user group 100 Aug 28 03:22 file2-rw-r--r-- 1 user group 100 Aug 28 03:22 file3352>[1] Done ls -laIt is common for the Done message to not be displayed immediately, for example it may onlybe displayed after the user’s next line of input (which can be a blank line as shown above). Thisis due to the status check only being called once per iteration of the main loop. Because thestatus check cannot block the shell, like it does with foreground processes, waitpid() shouldbe called in a non-blocking mode as discussed in lecture.Sometimes a process exits with a non-zero exit code, in that case the shell should display(replacing exitCode and commandArgs): Exit exitCode commandArgs352> grep &[1] 84867usage: grep [-abcDEFGHhIiJLlmnOoqRSsUVvwxZ] [-A num][-B num] [-C[num]] [-e pattern] [-f file][--binary-files=value] [--color=when][--context[=num]] [--directories=action] [--label][--line-buffered] [--null] [pattern] [file ...]352>[1] Exit 2 grepA process might not exit on its own and instead it is terminated using the kill command, whenthat happens the shell should display (replacing commandArgs): TerminatedcommandArgs.352> cat &[1] 84665352> kill 84665[1] Terminated catThe kill command works by sending an unhandled signal such as SIGTERM to a process. Youcan test if a child process was terminated in this way, as opposed to the process self-exitingwith a call to exit(), by using WIFSIGNALED.Finally, add the capacity to run multiple background processes concurrently.352> sleep 15 &[1] 85119352> sleep 8 &[2] 85120352> sleep 20 &[3] 85122352>[2] Done sleep 8352>[1] Done sleep 15352>[3] Done sleep 20Your shell can now perform sleep sort!Simplifying Assumption: You can assume that background commands will not contain a pipe. Inother words, you do not have to be concerned with command sequences such asls | grep txt &.Job Control CommandsJobs include background commands and stopped foreground commands. Implement thefollowing built-in commands to control jobs.jobsImplement the built-in jobs command which prints the list of background commands andstopped commands. The status of a job can be running or stopped. Background commandscreated with & are running by default. The following is an example.352> jobs[1] Stopped sleep 100[2] Running sleep 100 &[3] Running sleep 100 &The next two requirements provide situations where a command may switch between runningand stopped.control+zImplement control+z to stop the currently running foreground command. When a userpresses control+z, the terminal send the signal SIGTSTP (SIGnal - TerminalSToP) to the shell. Forwarding this signal, from the shell to the process running in theforeground, has already be implemented for you with the function sigtstpHandler().What still needs to be done, is the stopped command needs to be add to the list of jobs. Itsstatus is stopped.bg job_idImplement the bg job_id command which resumes a stopped command. The status of thecommand should be set to running. For example, consider the following scenario.352> sleep 100[User presses control+z.]352> jobs[1] Stopped sleep 100352> bg 1[1] Running sleep 100To make a process continue from a stopped state, send it a SIGCONT signal.Simplifying Assumption: You can assume that stoped commands will not contain a pipe. Inother words, you do not have to be concerned with the user pressing control+z on a commandsequence such as ls | grep txt.Additional Requirementsmakefile (5 points)You get 5 points for simply using a makefile. Name your source files whatever you like. Pleasename your executable shell352. Be sure that "make" will build your executable on pyrite.Documentation (10 points)If you have more than one source file, then you must submit a Readme file containing a briefexplanation of the functionality of each source file. Each source file must also be welldocumented.There should be a paragraph or so at the beginning of each source file describingthe code; functions and data structures should also be explained. Basically, anotherprogrammer should be able to understand your code from the comments.Project SubmissionPut all your source files (including the makefile and the README file) in a folder. Then usecommand zip -r <your ISU Net-ID> <src_folder> to create a .zip file. Forexample, if your Net-ID is ksmith and project1 is the name of the folder that contains allyour source files, then you will type zip -r ksmith project1 to create a file namedksmith.zip and then submit this file.Starter CodeYou are not required to use this code, however, it is highly recommended. Use the TODOs as aguide to start working on the project. ...

February 11, 2022 · 9 min · jiezi

关于c:kprobelf-高延迟内核函数定位分析工具

1.kprobe-lf是什么kprobe-lf是一款基于kprobe和中断定时器的高提早函数定位剖析工具 kprobe-lf能够定位剖析大多数内核函数,当设置提早足够小时也能够察看失常提早函数的堆栈 1.1 为什么叫kprobe-lf因为这款工具有两个重要的设置,一个是LATENCY,一个是FUNCTION,简称LF 1.2 适配问题目前在内核4.15.0,5.4.54,5.13.0上进行了测试,这几个版本都能够适配 2.如何应用git clone https://github.com/1978629634/kprobe_lf.gitcd kprobe_lfbash start.sh -f [FUNCTION_NAME] -l [LATENCY_TIME]运行脚本之后应用ctrl + c进行获取log,并且生成火焰图 脚本启动之后会在当前目录生成三个文件 lf.log 是函数运行前堆栈lf.svg 是火焰图lf.graph 是火焰图原始文件3.为什么须要kprobe-lf3.1 找到高提早首恶kprobe-lf能够定位超时函数并将它的运行堆栈制作成火焰图 比方咱们遇到软中断提早过长的问题时能够设置函数为__do_softirq,设置提早为1000us,定位剖析超时软中断 root@cluster1-worker1:~/kprobe_lf# bash start.sh -f __do_softirq -l 1000FUNCTION: __do_softirq, LATENCY_TIME: 1000 us (>=100us)find kprobe_lf.koinsmod kprobe_lf.kosave log to lf.log, ctrl + c to stop取得到超时__do_softirq运行时火焰图和超时__do_softirq运行前堆栈如下 运行时火焰图: 运行前堆栈: __do_softirq cpu:2 PID:0 COMMAND:swapper/2 LATENCY:5978us __do_softirq+0x1/0x2dc irq_exit+0xd5/0xe0 smp_apic_timer_interrupt+0x74/0x130 apic_timer_interrupt+0xf/0x20 native_safe_halt+0xe/0x10 default_idle+0x1c/0x140 do_idle+0x1aa/0x250 cpu_startup_entry+0x19/0x20 start_secondary+0x162/0x1c0 secondary_startup_64+0xa4/0xb0...通过LATENCY咱们能够晓得超时软中断提早高达6ms 通过火焰图咱们能够看到所有的高提早软中断都是在运行estimation_timer(IPVS BUG) 很快就能够定位到首恶函数 3.2 内核性能剖析在咱们对内核作性能剖析的状况下,有时想剖析批改一个参数对内核的性能影响是怎么的,咱们就能够利用这款工具对相干函数做剖析 ...

February 11, 2022 · 1 min · jiezi

关于c:csapp之第10章系统级I⁄O

0. 学习起因大多时候,高级别I/O函数工作良好,没必要间接用Unix I/O,为何需学习? 理解Unix I/O将帮忙了解其余零碎概念。I/O是零碎操作不可或缺的局部,因而常常遇到I/O和其余零碎概念之间的循环依赖有时必须用Unix I/O,用高级I/O不太可能或不适合,如规范I/O库没提供读取文件元数据的形式,此外I/O库存在一些问题1. Unix I/O输出/输入(I/O)是主存和外部设备之间复制数据的过程,在 Linux 中,文件就是字节的序列。所有的 I/O 设施(如网络、内核、磁盘和终端等)都被模型化为文件,而所有的输出和输入都被当作对相应文件的读和写来执行。这种将设施映射为文件的机制,容许内核引出简略、优雅的利用接口Unix I/O,使得所有输出和输入都以对立的形式执行,如 open()/close() 关上/敞开文件,read()/ write() 读/写文件。seek()扭转以后文件地位。Unix I/O次要分为两大类: 为辨别不同文件的类型,会有一个 type 来进行区别: 一般文件:蕴含任意数据目录:相干文件组的索引Socket:用于另一台机器上的过程通信还有一些特地的类型仅做理解:命名管道(FIFOs)、符号链接、字符和块设施 一般文件 一般文件蕴含任意数据,应用程序通常需辨别文本文件和二进制文件。前者只蕴含 ASCII 或 Unicode 字符。除此之外的都是二进制文件(对象文件, JPEG 图片, 等等)。内核不能辨别出区别。 文本文件是文本行的序列,每行以 \n 结尾,新行是 0xa,和 ASCII 码中LF一样。不同零碎判断行完结的符号不同(End of line, EOL),Linux & Mac OS是\n(0xa)等价line feed(LF),而Windows & 网络协议是\r\n (0xd 0xa)等价Carriage return(CR) followed by line feed(LF) 目录 目录蕴含一个链接(link)数组,且每个目录至多蕴含两记录:.(dot) 当前目录、..(dot dot) 下层目录 操作命令次要有 mkdir, ls, rmdir。目录以树状构造组织,根目录是 /(slash)。 内核会为每个过程保留当前工作目录(cwd, current working directory),可用 cd 命令进行更改。通过路径名来确定文件的地位,分为绝对路径和相对路径。 ...

February 8, 2022 · 4 min · jiezi

关于c:Redis使用SET命令覆盖旧值后旧值是同步还是异步删除

背景最近调研了redis大key的同步和异步删除形式,大key同步删除会造成主线程长时间阻塞。set命令笼罩旧值时,旧值的开释是同步还是异步执行的呢?查看源码在原key已有值时,set命令对应的操作函数为:/* Overwrite an existing key with a new value. Incrementing the reference * count of the new value is up to the caller. * This function does not modify the expire time of the existing key. * * The program is aborted if the key was not already present. */void dbOverwrite(redisDb *db, robj *key, robj *val) { dictEntry *de = dictFind(db->dict,key->ptr); serverAssertWithInfo(NULL,key,de != NULL); dictEntry auxentry = *de; robj *old = dictGetVal(de); if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) { val->lru = old->lru; } dictSetVal(db->dict, de, val); if (server.lazyfree_lazy_server_del) { /** * 异步删除旧值 */ freeObjAsync(old); /** * 将以后须要开释的旧值auxentry的值指针设置为NULL * 这样做是为了防止下一步的dictFreeVal操作执行实在的开释操作 */ dictSetVal(db->dict, &auxentry, NULL); } /** * 执行开释操作 */ dictFreeVal(db->dict, &auxentry);}能够看到,在服务器参数lazyfree_lazy_server_del为true时,redis服务器会采纳异步删除的形式,否则同步删除。配置项lazyfree_lazy_server_del参数能够通过配置文件中的lazyfree-lazy-server-del来进行管制,其值为yes或no。论断当lazyfree-lazy-server-del配置项的值为no时,redis的set操作采纳同步的形式开释旧值;值为yes时,采纳异步的形式开释旧值。lazyfree-lazy-server-del的默认值为no。

February 7, 2022 · 1 min · jiezi

关于c:csapp之labshell-lab

试验目标shell lab次要目标是为了相熟过程管制和信号。具体来说须要比对16个test和rtest文件的输入,实现五个函数: void eval(char *cmdline):剖析命令,并派生子过程执行 次要性能是解析cmdline并运行int builtin_cmd(char **argv):解析和执行bulidin命令,包含 quit, fg, bg, and jobsvoid do_bgfg(char **argv) 执行bg和fg命令void waitfg(pid_t pid):实现阻塞期待前台程序运行完结void sigchld_handler(int sig):SIGCHID信号处理函数void sigint_handler(int sig):信号处理函数,响应 SIGINT (ctrl-c) 信号 void sigtstp_handler(int sig):信号处理函数,响应 SIGTSTP (ctrl-z) 信号辅助函数可用辅助函数: int parseline(const char *cmdline,char **argv):获取参数列表,返回是否为后盾运行命令void clearjob(struct job_t *job):革除job构造体。void initjobs(struct job_t *jobs):初始化jobs链表。void maxjid(struct job_t *jobs):返回jobs链表中最大的jid号。int addjob(struct job_t *jobs,pid_t pid,int state,char *cmdline):在jobs链表中增加jobint deletejob(struct job_t *jobs,pid_t pid):在jobs链表中删除pid的job。pid_t fgpid(struct job_t *jobs):返回以后前台运行job的pid号。struct job_t *getjobpid(struct job_t *jobs,pid_t pid):返回pid号的job。struct job_t *getjobjid(struct job_t *jobs,int jid):返回jid号的job。int pid2jid(pid_t pid):将pid号转化为jid。void listjobs(struct job_t *jobs):打印jobs。void sigquit_handler(int sig):解决SIGQUIT信号。简介shell是交互式的命令行解释器,打印提示符并在stdin上期待输出命令,并依照命令行的内容执行。命令行是ASCII单词组成的命令和参数序列。若首个单词是内置命令,shell会立刻在以后过程中执行。否则是可执行文件门路,shell派生出子过程,而后在该子过程的上下文中加载和运行程序。解释单个命令行而创立的子过程叫作业,通常由Unix管道连贯的多个子过程组成。若命令行以&号“&”完结,则作业将在后盾运行且不会期待作业完结。否则作业将在前台运行且期待作业终止。故在任何工夫点最多仅一个作业在前台运行。但可在后盾运行任意数量的作业。 ...

February 2, 2022 · 16 min · jiezi

关于c:编程把INI文件转换成XML文件

来自宋劲波老师《linuxc》的习题 INI文件是一种很常见的配置文件,很多Windows程序都采纳这种格局的配置文件,在Linux零碎中Qt程序通常也采纳这种格局的配置文件。比方: ;Configuration of http[http]domain=www.mysite.comport=8080cgihome=/cgi-bin ;Configuration of db[database]server = mysqluser = mynamepassword = toopendatabase 一个配置文件由若干个Section组成,由[]括号括起来的是Section名。每个Section上面有若干个key = value模式的键值对(Key-value Pair),等号两边能够有零个或多个空白字符(空格或Tab),每个键值对占一行。以;号结尾的行是正文。每个Section完结时有一个或多个空行,空行是仅蕴含零个或多个空白字符(空格或Tab)的行。INI文件的最初一行前面可能有换行符也可能没有。当初XML衰亡了,INI文件显得有点土。当初要求编程把INI文件转换成XML文件首先咱们本人创立一个文本文件ini.txt如下: #include<stdio.h>#include<stdlib.h>#include<errno.h>#include<string.h>#define MAX_LINE 128//初始化buf用'\0'填充void ainit( char *buf ){ int i; for ( i = 0; i< MAX_LINE; i++ ) { buf[i] = '\0'; }}//将'\n'替换为'\0'void adell( char *buf ){ int i; for ( i = 0; buf[i] != '\0'; i++ ) { if ( buf[i] =='\n' ) { buf[i] = '\0'; } }}//去除数组中的'\t','空格'void abdel( char *buf ){ int i = 0, j = 0; for ( ; buf[i] != '\0'; i++ ) { if ( (buf[i] == '\t') || (buf[i] == ' ') ) { j = i; while ( buf[j] != '\0' ) { buf[j] = buf[j + 1]; j++; } i = i - 1; } }}int main(){ FILE *fp_xml,*fp_ini; //定义缓冲区 char buf[MAX_LINE] = {0}; char dbuf[MAX_LINE] = {0}; char ch = '\0'; char *kv, *key, *val; int i = 0; fp_ini = fopen("ini.txt","r+"); fp_xml = fopen("xml.txt","w+"); if ( fp_ini == NULL ) { perror("config.ini is not exist\n"); exit(1); } if ( fp_xml == NULL ) { perror("xml is not exist\n"); exit(1); } while((ch = fgetc(fp_ini)) != EOF){ if(ch == ';'){ //该语句管制</http>的打印和两个section之间的空一行 if( buf[0] != '\0' )//只有,此时曾经生成了<http>,由buf缓存,且并未flush时才成立 //所以该条件旨在生成第二个,即</http> fprintf( fp_xml, "</%s>\n\n", buf );//多空一行 //因为这个语句蕴含在while中(;语句转换之前),所以最初一个</xxxx>无奈生成 //见line:105来生成 //而后再进行;局部的转换 fgets(buf,MAX_LINE,fp_ini); adell(buf);//将;Configuration of http\n后跟的\n去掉,前面咱们本人管制换行 fprintf(fp_xml,"<!-- %s -->\n",buf); fflush(NULL);//该语句是确保所有文件写操作从cache传给内核到磁盘,不写也不影响 continue; } if(ch == '['){ ainit(buf);//持续利用buf进行[http]的转换 for(i = 0; (ch = fgetc(fp_ini)) != ']'; i++ ) { buf[i] = ch;//留神此处不能用fgets,咱们只有[]外部的字符,不要括号和\n } fprintf(fp_xml,"<%s>\n",buf); fflush(NULL); continue; } if((ch != '\n') && (ch != '\t') && (ch != ' ')){ ainit(dbuf); fgets(dbuf,MAX_LINE,fp_ini);//此处便能够间接获一行 // for( i = 0; (ch = fgetc(fp_ini)) != '\n' ; i++ ) { // dbuf[i] = ch; // }//如果用这个循环来给dbuf赋值会gdb提醒索引越界,未找到起因 adell(dbuf);//同上 abdel(dbuf);//后面如果有\t,以及两头夹的空格等都去掉 kv = dbuf; key = strtok(kv,"="); val = strtok(NULL,"=");//获取第一次截去后残余的字符串 fprintf(fp_xml," <%c%s>%s</%s>\n",ch,key,val,key);//留神此处ch //以后fgets读取的一行少了第一个字符(他被while中ch = fgetc()读去了,所以要把它补上) fflush(NULL); continue; } } fprintf(fp_xml, "</%s>", buf); fclose(fp_xml); fclose(fp_ini); return 0;}参考https://www.cnblogs.com/shish...这种写法应该工夫复杂度高一点,然而可读性好一点,适宜我这个老手!留神他的代码中失落了一个个字符:fprintf(fp_xml," <%c%s>%s</%s>\n",ch,key,val,key);//留神此处ch 以后fgets读取的一行少了第一个字符(他被while中ch = fgetc()读去了,所以要把它补上) ...

January 28, 2022 · 2 min · jiezi

关于c:Redis命令DEL与UNLINK的区别如何正确删除大Key

背景在这篇文章中做过应用del命令删除大key的试验,后果是del命令随着key的增大,主线程阻塞的工夫就越长。这与之前看redis5.0.8版本的代码中对于多线程删除操作的感官不符,于是决定先查看redis对于删除操作的代码,找出关键点,再做试验进行验证。筹备工作须要复用这篇文章中,应用过的数据构造方法和测试脚本代码。代码剖析步骤在server.c中找到redisCommandTable(命令表,redis的所有命令都对应这张表中的一个回调函数),找到del命令对应的回调函数delCommand。查看delCommand函数的代码内容如下:void delCommand(client *c) { delGenericCommand(c,0);}delCommand持续只是单纯的调用了一个通用删除办法delGenericCommand,持续追踪delGenericCommand,代码如下:/* This command implements DEL and LAZYDEL. */void delGenericCommand(client *c, int lazy) { int numdel = 0, j; for (j = 1; j < c->argc; j++) { expireIfNeeded(c->db,c->argv[j]); int deleted = lazy ? dbAsyncDelete(c->db,c->argv[j]) : dbSyncDelete(c->db,c->argv[j]); if (deleted) { signalModifiedKey(c->db,c->argv[j]); notifyKeyspaceEvent(NOTIFY_GENERIC, "del",c->argv[j],c->db->id); server.dirty++; numdel++; } } addReplyLongLong(c,numdel);}该办法就比拟有意思了,首先正文就说这个命令实现了删除和懒删除(也就是咱们想要的异步删除)。再看此行代码:int deleted = lazy ? dbAsyncDelete(c->db,c->argv[j]) : dbSyncDelete(c->db,c->argv[j]);也就是说依据参数lazy的不同而调用异步删除或同步删除。那么那里调用了这个办法,传递了什么参数呢?依据ide的追踪,发现有2个函数调用了以后函数,且lazy参数一个传0,一个传1,刚好对应了一个同步,一个异步。void delCommand(client *c) { delGenericCommand(c,0);}void unlinkCommand(client *c) { delGenericCommand(c,1);}其中,delCommand是del命令的回调,unlinkCommand是unlink命令的回调。这就阐明unlink命令才会让redis采纳异步删除的形式。试验验证结构数据和测试php脚本请参考这篇文章。首先采纳redis-cli --pipe的形式向redis增加一个key为sigkey的hash数据,其hlen为3000万,占用内存约1.8G。向redis增加一个key为m的string类型数据,用于测试获取。应用redis-cli连贯redis。开启测试php脚本。redis-cli中执行命令unlink ligkey。敞开观测php脚本,观测后果。试验后果有呈现标记信号的输入如下:0.57013500 1643333929--$4mack-------------------xxx---------------------0.70107700 1643333929--$4mack0.80816900 1643333929--$4mack0.92466400 1643333929--$4mack0.03091900 1643333930--$4mack0.13540800 1643333930--$4mack0.23995700 1643333930--$4mack0.34635700 1643333930--$4mack0.45889300 1643333930--$4mack0.56787100 1643333930--$4mack-------------------xxx---------------------0.69811500 1643333930--$4mack能够看到呈现稳定的两次距离均与0.13秒相差不大,且呈现这两个稳定的工夫节点与执行删除命令不同(执行命令的时候观测并未呈现标记),能够确认为失常网络稳定,排除unlink阻塞影响。总结依据源码剖析及理论试验操作可得,del命令应用同步删除,unlink应用异步删除。在删除数据体量很小的简略类型时倡议应用del命令,在删除大key时应该应用unlink命令。删除小key应用del的起因是:尽管del是同步删除,会阻塞主线程,然而unlink同样会在主线程执行一些判断和其它操作。而这些操作可能带来的开销比理论删除一个小key还略大。所以能间接删的key就没必要应用异步删除了。

January 28, 2022 · 1 min · jiezi

关于c:编程读写一个文件logcreatetxt每隔1秒向文件中写入一行记录

该程序应该有限循环,直到按Ctrl-C终止。下次再启动程序时在test.txt文件开端追加记录,并且序号可能接续上次的序号,比方: 1 2009-7-30 15:16:422 2009-7-30 15:16:433 2009-7-30 15:19:024 2009-7-30 15:19:035 2009-7-30 15:19:04这相似于很多零碎服务保护的日志文件.[阐明]获取以后的零碎工夫须要调用time()函数,返回的后果是一个time_t类型,其实就是一个大整数,其值示意从UTC(Coordinated Universal Time)工夫1970年1月1日00:00:00(称为UNIX零碎的Epoch工夫)到以后时刻的秒数。而后调用localtime()将time_t所示意的UTC工夫转换为本地工夫(咱们是+8区,比UTC多8个小时)并转成struct tm类型,该类型的各数据成员别离示意年月日时分秒,具体用法请查阅Man Page。调用sleep()函数能够指定程序睡眠多少秒。 #include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <unistd.h>//蕴含睡眠管制函数slepp();// struct tm//该构造体类型(tm)为内置类型,在time.h中,不必本人再反复定义// {// int tm_sec; /* 秒,范畴从 0 到 59 */// int tm_min; /* 分,范畴从 0 到 59 */// int tm_hour; /* 小时,范畴从 0 到 23 */// int tm_mday; /* 一月中的第几天,范畴从 1 到 31 */// int tm_mon; /* 月,范畴从 0 到 11(留神) */// int tm_year; /* 自 1900 年起的年数 */// int tm_wday; /* 一周中的第几天,范畴从 0 到 6 */// int tm_yday; /* 一年中的第几天,范畴从 0 到 365 */// int tm_isdst; /* 夏令时 */// };int main(){ FILE *file; struct tm *t1; time_t t;//c内置宏定义 // char * buf = (char *)malloc(100);不能定义成动静,要不每次执行过程会背地扭转行号 char buf[100]; int line = 0; memset(buf,0,sizeof(buf)); if ((file = fopen("log_create.txt", "a+")) < 0) { perror("failed to open log_create.txt"); exit(-1);//此处能够换成exit(1);exit(0)示意程序失常退出,非0示意非正常退出 } while( fgets(buf,sizeof(buf),file) != NULL){//逐行获取字符串 line++;//将用于记录的行号每次更新,下次计算时候要连接上 } while(1){ time(&t);//time_t time(time_t *timer), //如果 timer不为空,则返回值也存储在变量 timer即本例的t中 t1 = localtime(&t);//获取以后工夫 //struct tm *localtime(const time_t *timer) //应用 timer 的值来填充 tm 构造。timer 的值被合成为 tm 构造,并用本地时区示意 fprintf(file,"%d %d-%d-%d %d:%d:%d\n",++line, t1->tm_year + 1900, t1->tm_mon + 1, t1->tm_mday, t1->tm_hour, t1->tm_min, t1->tm_sec); //构造体tm中的tm_year是1900年到以后的工夫距离,tm_mom从一月开始,0代表一月 printf("%d %d-%d-%d %d:%d:%d\n",line, t1->tm_year + 1900, t1->tm_mon + 1, t1->tm_mday, t1->tm_hour, t1->tm_min, t1->tm_sec); fflush(file);//将改文件流cache写回缓存区,并使其写到内核或内存(设施)中! sleep(1);//能够指定程序睡眠多少秒 } fclose(file); return 0;}本函数以a+追加形式应用fopen()函数,不必本人创立文件,会主动生成并读写更新日志内容。能够看到,我第一次运行的后果如下: ...

January 27, 2022 · 1 min · jiezi

关于c:简单小游戏-剪刀石头步

首先阐明规定: 0、1、2三个整数别离是剪刀石头布在程序中的外部示意,用户也要求输出0、1或2,而后和计算机随机生成的0、1或2比输赢,这个程序的主体是一个死循环,须要按Ctrl-C退出程序! #include <stdio.h> #include <stdlib.h> #include <time.h> int main(void) { char gesture[3][10] = {"scissor", "stone","cloth"}; int man, computer, result, ret; srand(time(NULL)); while (1) { computer = rand() % 3; printf("\nInput your gesture (0-scissor 1 -stone 2 - cloth) :\n "); ret = scanf("%d", &man); if (ret != 1 || man < 0 || man > 2) { printf("Invalid input! Please input 0, 1 or 2.\n"); continue; } printf("Your gesture: %s\tComputer's gesture: % s\n ", gesture[man],gesture[computer]); result = (man - computer + 4) % 3 - 1; //此处为外围代码! if (result > 0) printf("You win!\n"); else if (result == 0) printf("Draw!\n"); else printf("You lose!\n"); } return 0; }依据对result的输赢判断条件可知,当result(即咱们输出的和电脑随机生成的后果通过计算之后的后果)大于0,咱们赢,小于0,咱们输,等于0,打成平手!那么(man - computer + 4) % 3 - 1这个神奇的表达式是如何管制比拟出0、1、2这三个数字在“剪刀石头布”意义上的大小和输赢的?凑的过程见上面表格: ...

January 25, 2022 · 1 min · jiezi

关于c:什么是安全函数

公司的大佬说之前某大厂为了平安函数的替换耗资10亿美金。可想平安很重要,平安函数很重要,对于咱们做系统软件的来说很重要。为什么要替换成平安函数,这外面就波及到了一种破绽攻打,缓冲区溢出攻打。 缓冲区溢出是指当计算机向缓冲区内填充数据位数时超过了缓冲区自身的容量,溢出的数据笼罩在非法数据上。现实的状况是:程序会检查数据长度,而且并不容许输出超过缓冲区长度的字符。然而绝大多数程序都会假如数据长度总是与所调配的贮存空间相匹配,这就为缓冲区溢出埋下隐患。操作系统所应用的缓冲区,又被称为“堆栈”,在各个操作过程之间,指令会被长期贮存在“堆栈”当中,“堆栈”也会呈现缓冲区溢出。缓冲区溢出攻打是利用缓冲区溢出破绽所进行的攻打口头。利用缓冲区溢出攻打,能够导致程序运行失败、零碎关机、重新启动等结果。 缓冲区溢出中,最为危险的是堆栈溢出,因为入侵者能够利用堆栈溢出,在函数返回时扭转返回程序的地址,让其跳转到任意地址,带来的危害一种是程序解体导致拒绝服务分段谬误(Segmentation fault),另外一种就是跳转并且执行一段恶意代码,比方失去shell,而后随心所欲。 C语言没有提供字符串类型,字符串以字符数组的模式呈现,C规范库提供了一些操作字符串的函数,次要有:strcmp 字符串比拟函数,strcpy 字符串拷贝函数, strlen 字符串测长函数, strcat字符串连贯函数,sprintf格式化字符串拷贝函数等等。因为字符串就是以‘\0’完结的一段内存,这些函数本质上也就是操作内存的函数。 也就是说,平安函数和非平安函数最大的差别就是:为了避免堆栈溢出,平安函数多了一个确定buff长度的参数。 举个例子: 非平安函数: 头文件:#include <string.h>函数原型:char *strcpy(char *dest, const char *src);函数阐明:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间。src和dest所指内存区域不能够重叠且dest必须有足够的空间来包容src的字符串。平安函数: 头文件:#include <string.h>函数原型:char *strncpy(char *dest, const char *src, size_t n);函数阐明:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间。最多复制n个字符。src和dest所指内存区域不能够重叠且dest必须有足够的空间来包容src的字符串。关注&&分割开源轻量操作系统: https://gitee.com/cmcc-oneos/OneOS-Lite docs文档核心: https://oneos-lite.com/

January 18, 2022 · 1 min · jiezi

关于c:SNAT的MASQUERADE地址选择与端口选择

环境:版本:kernel-5.4.54 amd64 双核 ubuntu18.04k8s集群网络组件:flannel,kube-proxy: ipvs代码工具:vs code1.概述SNAT(源地址转换)是IPTABLES的NAT表的外围性能,广泛应用与路由器,云服务器,K8S集群等内网环境中,是内核网络子系统中不可或缺的性能IPTABLES的NAT齐全依赖于netfilter的conntrack,对于没有进行conntrack的数据包无奈进行NAT在K8S集群中DNAT用于负载平衡,SNAT用来保障节点转发的数据包能回到节点去实现de-DNAT还原,而不是间接发给客户端。 客户端拜访的是负载平衡IP,后端IP间接回包给客户端的话,客户端无奈辨认;后端IP回包先转给负载均衡器,将后端IP还原成负载平衡IP之后再发给客户端IPTABLES和IPVS都能够实现DNAT负载平衡的性能,然而SNAT只能由IPTABLES实现查看集群中IPTABLES的SNAT规定root@cluster1-worker1:~# iptables -t nat -nLChain PREROUTING (policy ACCEPT)target prot opt source destination KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCALChain INPUT (policy ACCEPT)target prot opt source destination Chain OUTPUT (policy ACCEPT)target prot opt source destination KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCALChain POSTROUTING (policy ACCEPT)target prot opt source destination KUBE-POSTROUTING all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes postrouting rules */MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0 RETURN all -- 10.244.0.0/16 10.244.0.0/16 MASQUERADE all -- 10.244.0.0/16 !224.0.0.0/4 RETURN all -- !10.244.0.0/16 10.244.2.0/24 MASQUERADE all -- !10.244.0.0/16 10.244.0.0/16 ...Chain KUBE-POSTROUTING (1 references)target prot opt source destination /* Kubernetes endpoints dst ip:port, source ip for solving hairpin purpose */ MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-LOOP-BACK dst,dst,srcRETURN all -- 0.0.0.0/0 0.0.0.0/0 mark match ! 0x4000/0x4000MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK xor 0x4000/* kubernetes service traffic requiring SNAT */MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 ...剖析MASQUERADE是如何SNAT的对于咱们理解集群间网络通信很有帮忙 ...

January 10, 2022 · 6 min · jiezi

关于c:IPTABLES的连接跟踪与NAT分析

1.Netfilter 结构图Netfilter框架的外围是五个钩子点,能够通过在钩子点注册函数,实现过滤批改数据包的性能IPTABLES和IPVS就是通过注册钩子函数的形式来实现它们的次要性能的ip_rcv是三层协定栈的入口函数dev_queue_xmit最初会调用网络设备驱动发送数据包包 2.Netfilter & CONNTRACK & IPTABLES NAT 结构图 2.1 Netfilter的每个钩子点的钩子函数都有不同的优先级/* hook函数默认优先级设置,数值越小优先级越高 */enum nf_ip_hook_priorities { NF_IP_PRI_FIRST = INT_MIN, /* 最高优先级 */ NF_IP_PRI_RAW_BEFORE_DEFRAG = -450, /* 波及IP分片重组的RAW */ NF_IP_PRI_CONNTRACK_DEFRAG = -400, /* 波及IP分片重组的连贯跟踪 */ NF_IP_PRI_RAW = -300, /* RAW表,用于勾销连贯跟踪 */ NF_IP_PRI_SELINUX_FIRST = -225, NF_IP_PRI_CONNTRACK = -200, /* 连贯跟踪开始 */ NF_IP_PRI_MANGLE = -150, NF_IP_PRI_NAT_DST = -100, /* NAT的扭转目标地址, DNAT or de-SNAT */ NF_IP_PRI_FILTER = 0, /* IPTABLES的数据包过滤 */ NF_IP_PRI_SECURITY = 50, NF_IP_PRI_NAT_SRC = 100, /* NAT的扭转源地址, SNAT or de-DNAT */ NF_IP_PRI_SELINUX_LAST = 225, NF_IP_PRI_CONNTRACK_HELPER = 300, NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX, /* 连贯确认 */ NF_IP_PRI_LAST = INT_MAX, /* 最低优先级 */};优先级CONNTRACK > DNAT > FILTER > SNAT > CONNTRACK_CONFIRM3.CONNTRACK3.1 conntrack注册的钩子static const struct nf_hook_ops ipv4_conntrack_ops[] = { { .hook = ipv4_conntrack_in, /* return nf_conntrack_in */ .pf = NFPROTO_IPV4, .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_CONNTRACK, }, { .hook = ipv4_conntrack_local, /* return nf_conntrack_in */ .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_CONNTRACK, }, { .hook = ipv4_confirm, /* 调用nf_conntrack_confirm */ .pf = NFPROTO_IPV4, .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP_PRI_CONNTRACK_CONFIRM, }, { .hook = ipv4_confirm, /* 调用nf_conntrack_confirm */ .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_CONNTRACK_CONFIRM, },};3.2 nf_conntrack_innf_conntrack_in是conntrack的外围函数,次要作用是: ...

January 10, 2022 · 9 min · jiezi

关于c:IPVS分析

1.Netfilter & CONNTRACK & IPVS结构图 2.IPVSipvs只有DNAT和de-DNAT性能 ,它独立与iptables和conntrack,实现了本人的一套连贯跟踪表和NAT机制 2.1 ipvs与conntrack的分割:ipvs仅仅在做DNAT后对conntrack连贯进行更新,避免回包因为没有记录而被抛弃ipvs在TUNNEL模式下,会调用nf_conntrack_confirm函数对连贯进行确认 2.2 ipvs注册的钩子函数static const struct nf_hook_ops ip_vs_ops[] = { /* After packet filtering, change source only for VS/NAT */ { .hook = ip_vs_reply4, /* ip_vs_out */ .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_NAT_SRC - 2, }, /* After packet filtering, forward packet through VS/DR, VS/TUN, * or VS/NAT(change destination), so that filtering rules can be * applied to IPVS. */ { .hook = ip_vs_remote_request4, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_NAT_SRC - 1, }, /* Before ip_vs_in, change source only for VS/NAT */ { .hook = ip_vs_local_reply4, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_NAT_DST + 1, }, /* After mangle, schedule and forward local requests */ { .hook = ip_vs_local_request4, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_NAT_DST + 2, }, /* After packet filtering (but before ip_vs_out_icmp), catch icmp * destined for 0.0.0.0/0, which is for incoming IPVS connections */ { .hook = ip_vs_forward_icmp, .pf = NFPROTO_IPV4, .hooknum = NF_INET_FORWARD, .priority = 99, }, /* After packet filtering, change source only for VS/NAT */ { .hook = ip_vs_reply4, .pf = NFPROTO_IPV4, .hooknum = NF_INET_FORWARD, .priority = 100, },};2.3 IPVS中tcp协定的状态转换表/* * Timeout table[state] */static const int tcp_timeouts[IP_VS_TCP_S_LAST+1] = { [IP_VS_TCP_S_NONE] = 2*HZ, [IP_VS_TCP_S_ESTABLISHED] = 15*60*HZ, [IP_VS_TCP_S_SYN_SENT] = 2*60*HZ, [IP_VS_TCP_S_SYN_RECV] = 1*60*HZ, [IP_VS_TCP_S_FIN_WAIT] = 2*60*HZ, [IP_VS_TCP_S_TIME_WAIT] = 2*60*HZ, [IP_VS_TCP_S_CLOSE] = 10*HZ, [IP_VS_TCP_S_CLOSE_WAIT] = 60*HZ, [IP_VS_TCP_S_LAST_ACK] = 30*HZ, [IP_VS_TCP_S_LISTEN] = 2*60*HZ, [IP_VS_TCP_S_SYNACK] = 120*HZ, [IP_VS_TCP_S_LAST] = 2*HZ,};#define sNO IP_VS_TCP_S_NONE#define sES IP_VS_TCP_S_ESTABLISHED#define sSS IP_VS_TCP_S_SYN_SENT#define sSR IP_VS_TCP_S_SYN_RECV#define sFW IP_VS_TCP_S_FIN_WAIT#define sTW IP_VS_TCP_S_TIME_WAIT#define sCL IP_VS_TCP_S_CLOSE#define sCW IP_VS_TCP_S_CLOSE_WAIT#define sLA IP_VS_TCP_S_LAST_ACK#define sLI IP_VS_TCP_S_LISTEN#define sSA IP_VS_TCP_S_SYNACKstatic struct tcp_states_t tcp_states[] = {/* INPUT ip_vs_in调用 *//* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA 初始状态 *//*syn*/ {{sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR }},/*fin*/ {{sCL, sCW, sSS, sTW, sTW, sTW, sCL, sCW, sLA, sLI, sTW }},/*ack*/ {{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }},/*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sSR }},/* OUTPUT ip_vs_out调用 *//* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA 初始状态 *//*syn*/ {{sSS, sES, sSS, sSR, sSS, sSS, sSS, sSS, sSS, sLI, sSR }},/*fin*/ {{sTW, sFW, sSS, sTW, sFW, sTW, sCL, sTW, sLA, sLI, sTW }},/*ack*/ {{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sLA, sES, sES }},/*rst*/ {{sCL, sCL, sSS, sCL, sCL, sTW, sCL, sCL, sCL, sCL, sCL }},/* INPUT-ONLY ip_vs_in在没有收到回包时调用*//* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA *//*syn*/ {{sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR }},/*fin*/ {{sCL, sFW, sSS, sTW, sFW, sTW, sCL, sCW, sLA, sLI, sTW }},/*ack*/ {{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }},/*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sCL }},};2.4 ip_vs_in为目的地为虚构服务器的数据包确认连贯,并为连贯调配后端,而后转发数据包 ...

January 10, 2022 · 9 min · jiezi

关于c:LeetCode刷题学习278第一个错误的版本使用二分查找解决01模型问题

C语言二分查找解决 01模型从000000011111111中找到第一个1样例输出:n = 5, bad = 4输入:4解释:调用 isBadVersion(3) -> false 调用 isBadVersion(5) -> true 调用 isBadVersion(4) -> true所以,4 是第一个谬误的版本 int firstBadVersion(int n) { int i=1; int j=n; while(i<j){ int mid=i+(j-i)/2; if(!isBadVersion(mid)){ i=mid+1; } else if(isBadVersion(mid)){ j=mid; } } return i;}

January 10, 2022 · 1 min · jiezi

关于c:LeetCode刷题学习704二分查找

二分查找C语言版本LeetCode 704题给定正序数组,应用二分查找测试样例输出: nums = [-1,0,3,5,9,12], target = 9输入: 4解释: 9 呈现在 nums 中并且下标为 4 int search(int* nums, int numsSize, int target){ int i=0; int j=numsSize-1; while(i<=j){ int mid=(j-i)/2+i; if(target==nums[mid]){ return mid; } else if(target>nums[mid]){ i=mid+1; } else if(target<nums[mid]){ j=mid-1; } } return -1;}

January 10, 2022 · 1 min · jiezi

关于c:TCP协议connect的端口选择

connect端口抉择在socket编程中, 客户端应用connect向服务端发动申请时,如果不指定本地端口(个别都不指定), 内核会主动为连贯调配一个可用的端口. connect是如何进行端口抉择的呢?connect端口抉择逻辑如下: 如果sock曾经指定了端口, 应用指定的端口如果sock没有指定端口, 调配一个端口 先获取内核参数设置的本地可用端口范畴,默认为low: 32768 - high: 60999依据hint和三元组的hash失去一个随机的偏移量offset从low+offset开始, 在可用端口范畴内遍历判断端口是否可用, 每次端口值+2 不容许应用用户设置的保留端口如果端口曾经应用 不容许应用bind绑定的端口查看端口是否可重用 1. ehash表中没有四元组匹配的sock时端口可重用2. 有四元组匹配的sock时进行TIME_WAIT判断 1. 合乎以下条件可重用 1. 匹配的连贯处于TIME_WAIT状态 2. 满足TIME_WAIT端口复用条件如果端口没有被应用,应用此端口内核容许同一个端口向两个不同的服务端发动连贯申请 源码剖析:connect端口抉择外围函数inet_hash_connect剖析:/* * Bind a port for a connect operation and hash it. */int inet_hash_connect(struct inet_timewait_death_row *death_row, struct sock *sk){ u32 port_offset = 0; /* 如果sk的本地源端口设置为0 */ if (!inet_sk(sk)->inet_num) /* 依据源IP、目标IP、目标端口,用hash函数计算出一个随机数,作为端口的初始偏移值 */ port_offset = inet_sk_port_offset(sk); return __inet_hash_connect(death_row, sk, port_offset, __inet_check_established); /* __inet_check_established为查看端口是否可用的回调函数 */}__inet_hash_connect剖析:int __inet_hash_connect(struct inet_timewait_death_row *death_row, struct sock *sk, u32 port_offset, int (*check_established)(struct inet_timewait_death_row *, struct sock *, __u16, struct inet_timewait_sock **)){ struct inet_hashinfo *hinfo = death_row->hashinfo; struct inet_timewait_sock *tw = NULL; struct inet_bind_hashbucket *head; int port = inet_sk(sk)->inet_num; struct net *net = sock_net(sk); struct inet_bind_bucket *tb; u32 remaining, offset; int ret, i, low, high; static u32 hint; int l3mdev; /* sock曾经设置了端口 */ if (port) { head = &hinfo->bhash[inet_bhashfn(net, port, hinfo->bhash_size)]; tb = inet_csk(sk)->icsk_bind_hash; spin_lock_bh(&head->lock); if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) { inet_ehash_nolisten(sk, NULL); spin_unlock_bh(&head->lock); return 0; } spin_unlock(&head->lock); /* No definite answer... Walk to established hash table */ ret = check_established(death_row, sk, port, NULL); local_bh_enable(); return ret; } /* * sock没有设置端口时会走到这里,以下是内核主动抉择端口的过程 * connect主动抉择端口会保障和ip_local_port_range的low的奇偶性保持一致 * bind主动抉择端口会保障和low奇偶性相同 */ /* * 绑定的VRF(Virtual Routing and Forwarding)设施 * 内核默认不开启tcp_l3mdev_accept,间接返回0 */ l3mdev = inet_sk_bound_l3mdev(sk); /* 获取本地可用端口范畴,ip_local_port_range是能够设置的内核参数,默认是32768-60999 */ inet_get_local_port_range(net, &low, &high); high++; /* [32768, 60999] -> [32768, 61000[ */ /* 计算端口范畴差值 */ remaining = high - low; if (likely(remaining > 1)) /* 确保remaining为偶数,保障和low的奇偶性保持一致 */ remaining &= ~1U; /* * 依据hint和port_offset计算出一个remaining范畴内的偏移量 * hint是一个动态变量,每次+(i+2),i为上次的可用端口-初始抉择端口 * hint尽量使每次抉择的端口递增,进步端口命中率 * port_offset是之前依据源地址,目标地址,目标端口hash进去的一个随机数 */ offset = (hint + port_offset) % remaining; /* In first pass we try ports of @low parity. * inet_csk_get_port() does the opposite choice. */ /* 确保offset为偶数,保障和low的奇偶性保持一致 */ offset &= ~1U;other_parity_scan: /* 抉择第一个port的值 */ port = low + offset; /* 从第一个port开始判断端口是否可用,每次port+2,保障和low的奇偶性保持一致 */ for (i = 0; i < remaining; i += 2, port += 2) { /* port超范围则返回low持续查找 */ if (unlikely(port >= high)) port -= remaining; /* * 排除ip_local_reserved_ports内核参数中设置的保留端口 * 参数默认为空,能够本人配置想要为某些服务保留的端口 */ if (inet_is_local_reserved_port(net, port)) continue; /* 依据端口号和命名空间的哈希失去哈希表头 */ head = &hinfo->bhash[inet_bhashfn(net, port, hinfo->bhash_size)]; /* 锁住此表头 */ spin_lock_bh(&head->lock); /* Does not bother with rcv_saddr checks, because * the established check is already unique enough. */ /* 从哈希失去的链表中查找对应的命名空间和端口号的bind_bucket */ inet_bind_bucket_for_each(tb, &head->chain) { /* 比照命名空间,端口号和VRF设施(默认不开启) */ if (net_eq(ib_net(tb), net) && tb->l3mdev == l3mdev && tb->port == port) { /* 不容许应用bind创立或者应用的端口 * bind创立构造体时,会使得fastreuse和fastreuseport>=0 * connect创立构造体时,两个值为-1 */ if (tb->fastreuse >= 0 || tb->fastreuseport >= 0) goto next_port; WARN_ON(hlist_empty(&tb->owners)); /* 查看端口是否可重用 * 1.ehash表中没有四元组,命名空间匹配的sock时可重用 * 2.有四元组命名空间匹配的连贯时进行TIME_WAIT判断 * 合乎以下条件可重用 * - 匹配的连贯处于TIME_WAIT状态 * - 满足TIME_WAIT端口复用条件 */ if (!check_established(death_row, sk, port, &tw)) goto ok; goto next_port; } } /* 没有找到对应的bind_bucket时会走到这里 * 阐明还没有创立端口的inet_bind_bucket构造,端口肯定可用 */ /* 为端口创立inet_bind_bucket构造 */ tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep, net, head, port, l3mdev); if (!tb) { spin_unlock_bh(&head->lock); return -ENOMEM; } /* fastreuse和fastreuseport设置为-1 */ tb->fastreuse = -1; tb->fastreuseport = -1; goto ok;next_port: spin_unlock_bh(&head->lock); cond_resched(); } /* 走到这里阐明没有适合端口,扭转奇偶性再选一次 */ offset++; if ((offset & 1) && remaining > 1) goto other_parity_scan; /* 扭转奇偶性仍然没有适合端口,返回谬误Cannot assign requested address */ return -EADDRNOTAVAIL;ok: /* 保留动态变量的值,下个雷同三元组会应用新的hint,缩小反复判断 */ hint += i + 2; /* Head lock still held and bh's disabled */ /* 将sock增加到inet_bind_bucket构造的owner链表中 */ inet_bind_hash(sk, tb, port); /* 如果sokc没有增加到ehash表,将sock增加到ehash表中 */ if (sk_unhashed(sk)) { inet_sk(sk)->inet_sport = htons(port); inet_ehash_nolisten(sk, (struct sock *)tw); } /* 提前结束time_wait状态 */ if (tw) inet_twsk_bind_unhash(tw, hinfo); spin_unlock(&head->lock); if (tw) inet_twsk_deschedule_put(tw); local_bh_enable(); return 0;}__inet_check_established剖析:/* called with local bh disabled */static int __inet_check_established(struct inet_timewait_death_row *death_row, struct sock *sk, __u16 lport, struct inet_timewait_sock **twp){ struct inet_hashinfo *hinfo = death_row->hashinfo; struct inet_sock *inet = inet_sk(sk); __be32 daddr = inet->inet_rcv_saddr; __be32 saddr = inet->inet_daddr; int dif = sk->sk_bound_dev_if; struct net *net = sock_net(sk); int sdif = l3mdev_master_ifindex_by_index(net, dif); INET_ADDR_COOKIE(acookie, saddr, daddr); const __portpair ports = INET_COMBINED_PORTS(inet->inet_dport, lport); /* 依据四元组和命名空间失去ehash表的哈希值 */ unsigned int hash = inet_ehashfn(net, daddr, lport, saddr, inet->inet_dport); /* 获取指定哈希值的哈希桶 */ struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash); /* 指定哈希桶的锁 */ spinlock_t *lock = inet_ehash_lockp(hinfo, hash); struct sock *sk2; const struct hlist_nulls_node *node; struct inet_timewait_sock *tw = NULL; /* 锁住哈希桶 */ spin_lock(lock); /* 遍历哈希桶匹配四元组,命名空间,绑定设施雷同的sock */ sk_nulls_for_each(sk2, node, &head->chain) { /* 比拟hash值 */ if (sk2->sk_hash != hash) continue; /* 有四元组,命名空间,绑定设施齐全匹配的连贯 */ if (likely(INET_MATCH(sk2, net, acookie, saddr, daddr, ports, dif, sdif))) { /* 连贯处于TIME_WAIT状态 */ if (sk2->sk_state == TCP_TIME_WAIT) { tw = inet_twsk(sk2); /* 判断是否满足TIME_WAIT端口复用条件 */ if (twsk_unique(sk, sk2, twp)) break; } /* 如果有齐全匹配的连贯,且不可TIME_WAIT复用,会走到这里,返回不可用 */ goto not_unique; } } /* 没有匹配到雷同的连贯,或者time_wait重用会走到这里 */ /* Must record num and sport now. Otherwise we will see * in hash table socket with a funny identity. */ inet->inet_num = lport; inet->inet_sport = htons(lport); sk->sk_hash = hash; WARN_ON(!sk_unhashed(sk)); /* 增加sock到ehash哈希桶中 */ __sk_nulls_add_node_rcu(sk, &head->chain); /* 从ehash哈希桶中删除TIME_WAIT连贯 */ if (tw) { sk_nulls_del_node_init_rcu((struct sock *)tw); __NET_INC_STATS(net, LINUX_MIB_TIMEWAITRECYCLED); } spin_unlock(lock); /* 减少端口应用计数 */ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); /* 提前终止time_wait */ if (twp) { *twp = tw; } else if (tw) { /* Silly. Should hash-dance instead... */ inet_twsk_deschedule_put(tw); } /* 返回可用 */ return 0;not_unique: spin_unlock(lock); return -EADDRNOTAVAIL;}

January 5, 2022 · 4 min · jiezi

关于c:C标识符最长长度

visual studio 2019编译器下,c标识符长度 最长为4095个,半角字符输出一个字符占用一个字符,全角字符占用两个字符,汉字占用两个字符。超过则会报错 作者:点墨版权:本文版权归作者所有转载:欢送转载,但未经作者批准,必须保留此段申明;必须在文章中给出原文连贯;否则必究法律责任

January 4, 2022 · 1 min · jiezi

关于c:C进阶28指针和数组分析

Summary1)数组是一段间断的内存空间,数组的元素个数为 #define DIM(a) (sizeof(a) / sizeof(*a)) 2)指针是一种非凡的变量,与整数的运算规定为: p + n; <--> (unsigned int)p + n * sizeof(*p)当指针p指向一个数组里的元素时,p + 1将指向以后元素的下一元素;p - 1将指向以后元素的上一元素。 3)指针之间只反对减法运算;参加减法运算的指针必须类型雷同:留神:只有当2个指针指向同一个数组中的元素时,指针相减才有意义,意义为指针所指元素的下标差;当2个指针指向的元素不在同一个数组时,未定义。p1 - p2; <--> ((unsigned int)p1 - (unsigned int)p2) / sizeof(type); 4)char* pEnd = s + DIM(s); pEnd指向了数组s中最初一个元素的后一地位,尽管这个地位不属于数组,但在C语言中,依然认为这个边界地位是属于数组的,这个知识点在STL中也有利用。 5)指针也能够进行关系运算(<, <=, >, >=),但前提是同时指向同一个数组中的元素;两个指针间能够进行比拟运算(==,!=),但两个指针的类型必须雷同; 6)for (p = pBegin; p < pEnd; p++) ,p指向了数组的首元素,pEnd在C语言中被认为是数组的元素,所以p和pEnd都指向了同一个数组里的元素,类型雷同,可能进行比拟。 指针和数组剖析数组是一段间断的内存空间数组的空间大小为 sizeof(arr_type) * arr_size数组名可看做指向数组第一个元素的指针常量 1、指针的运算问题:对于数组int a[5],a + 1的意义是什么?后果是什么?指针运算的意义是什么,后果又是什么? 论断:指针是一种非凡的变量,与整数的运算规定为: p + n; <--> (unsigned int)p + n * sizeof(*p)当指针p指向一个数组里的元素时,p + 1将指向以后元素的下一元素;p - 1将指向以后元素的上一元素。 ...

December 30, 2021 · 3 min · jiezi

关于c:Mac-OS上用命令行执行C程序

用命令行新建C文件touch hello.c编辑C文件vim hello.c编写C程序代码#include <stdio.h>int main(){ printf("Hello World!"); return 0;} 编译C程序文件cc -c hello.c 生成可执行文件cc hello.o 执行文件./a.out

December 30, 2021 · 1 min · jiezi

关于c:C进阶27数组的本质分析

Summary1)数组是雷同类型的变量的有序汇合,数组在一片间断的内存空间中存储元素。 2)数组名a代表数组首元素的地址,a同时也代表数组这一段间断的内存; a是数组首元素的地址,类型是int*;*a就是首元素,sizeof(*a)能够取得数组首元素的内存大小;a同时也代表这一段内存,sizeof(a)能够取得数组的内存大小;sizeof(a) / sizeof(*a) = 数组元素的个数3)数组的地址须要用取地址符&取到,&a; &a是数组的地址,类型是int(*)[n].4)数组首元素的地址值与数组的地址 值雷同,然而意义不同;(比方现实生活中,小区的地址和我家的地址是雷同的,但并不能说小区就是我家的)咱们所说的地址通常蕴含2个概念:起始地址 + 长度 在值上,a == &a[0] == &a;但意义不同,体现在指针运算上,a + 1,会挪动sizeof(*a)个字节,&a + 1,会挪动sizeof(a)个字节5) 数组名能够看做一个指针常量(留神是看做,数组名并不是指针),因为数组名指向的是首元素的起始地位,是一个地址,并且不能作为左值,同时数组名在很多时候能够像指针一样操作,比方指针运算等。 6)在下列场合中,数组名就不能看做指针常量(也证实了数组名并不是指针) 数组名作为sizeof的参数,这时候取的是数组内存的大小。(a就不是个指针了,如果看做指针,就永远取到的是4或8字节,而不是数组a的大小)数组作为&运算符的参数,此时取到的是数组a的地址,同首元素的值。数组的实质剖析1、数组的概念数组是雷同类型的变量的有序汇合,数组在一片间断的内存空间中存储元素。 数组元素的个数能够显示或隐式指定: 详见:【C入门】7、C语言中的数组int a[5] = {1, 2};int b[] = {1, 2};问题:1. a[2], a[3], a[3]的值是多少? -- 0,如果后面的元素指定了值,后续未初始化的均为02. b蕴含了多少个元素? -- 2,编译器会隐式推断b有多少元素2、数组名的盲点2.1 数组名a代表数组首元素的地址,a同时也代表数组这一段间断的内存; a是数组首元素的地址,类型是int*;*a就是首元素,sizeof(*a)能够取得数组首元素的内存大小;a同时也代表这一段内存,sizeof(a)能够取得数组的内存大小;sizeof(a) / sizeof(*a) = 数组元素的个数2.2 数组的地址须要用取地址符&取到,&a; &a是数组的地址,类型是int(*)[n].2.3 数组首元素的地址值与数组的地址 值雷同,然而意义不同;(比方现实生活中,小区的地址和我家的地址是雷同的,但并不能说小区就是我家的)咱们所说的地址通常蕴含2个概念:起始地址 + 长度 在值上,a == &a[0] == &a;但意义不同,体现在指针运算上,a + 1,会挪动sizeof(*a)个字节,&a + 1,会挪动sizeof(a)个字节2.4 数组名能够看做一个指针常量(留神是看做,数组名并不是指针),因为数组名指向的是首元素的起始地位,是一个地址,并且不能作为左值,同时数组名在很多时候能够像指针一样操作,比方指针运算等。 2.5 在下列场合中,数组名就不能看做指针常量(也证实了数组名并不是指针) 数组名作为sizeof的参数,这时候取的是数组内存的大小。(a就不是个指针了,如果看做指针,就永远取到的是4或8字节,而不是数组a的大小)数组作为&运算符的参数,此时取到的是数组a的地址,同首元素的值。本文总结自“狄泰软件学院”唐佐林老师《C语言进阶课程》。如有错漏之处,恳请斧正。

December 29, 2021 · 1 min · jiezi

关于c:C进阶26指针的本质分析

Summary1)指针的实质是变量,非凡在于存储的内容是一段内存地址。 2)在指针申明时,*号示意所申明的变量为指针;在指针应用时,*号示意取指针所指向的内存空间中的值 3)指针作为函数参数: 指针是变量,因而能够申明指针参数当一个函数体外部须要扭转实参的值则须要应用指针参数;函数调用时实参值将复制到形参指针实用于简单数据类型作为参数的函数中4)口诀:左数右指 -- 当const呈现在*号左侧时,指向的数据为常量;当const呈现在*号右侧时,指针为常量。 const int* p; // 指针p可变,指向的数据*p不可变int const* p; // 指针p可变,指向的数据*p不可变int* const p; // 指针p不可变,指向的数据*p可变const int* const p; // 指针p不可变,指向的数据*p也不可变指针的实质剖析问题:程序中的变量只是一段存储空间的别名,那么是不是必须通过这个别名能力应用这段存储空间? 1、指针的申明和应用上面的程序输入什么?为什么 int i = 5;int* p = &i;printf("%d, %p\n", i, p); // 5, 0XBFDB216C*p = 10;printf("%d, %p\n", i, p); // 10, 0XBFDB216C在指针申明时,*号示意所申明的变量为指针在指针应用时,*号示意取指针所指向的内存空间中的值2、传值调用和传址调用指针是变量,因而能够申明指针参数当一个函数体外部须要扭转实参的值,则须要应用指针参数函数调用时实参值将复制到形参指针实用于简单数据类型作为参数的函数中 // 指针作为参数剖析void swap1(int a, int b){ int t = a; a = b; b = a;}void swap2(int* pa, int* pb){ int t = *pa; *pa = *pb; *pb = t;}int main(){ int a = 1, b = 2; swap1(a, b); // 将实参a和b的值,赋值给swap1参数a、b,函数外部理论批改的是函数的形参a和b,不会影响实参 printf("%d, %d\n", a, b); // 1, 2 swap2(&a, &b); // 将实参a和b的地址,赋值给参数指针pa和pb,函数外部应用*号关上了这两个地址,并批改了外面的值,所以里面的实参也会变 printf("%d, %d\n", a, b); // 2, 1 return 0;}3、const和指针口诀:左数右指 -- 当const呈现在*号左侧时,指向的数据为常量;当const呈现在*号右侧时,指针为常量。 ...

December 27, 2021 · 1 min · jiezi

关于c:C进阶25和运算符

Summary1)'#'用于在预处理期将宏参数转换为字符串;只在宏定义中无效,编译器不晓得'#'的存在 2)能够应用#+函数名,在调用时打印函数名 3)'##'用于在预处理期 拼接两个标识符;只在宏定义中无效,编译器不晓得'##'的存在 4)能够应用'##'疾速定义构造体、应用构造体,疾速定义类等。 ·#和##运算符剖析1、'#''#'运算符用于在预处理期将宏参数转换为字符串(给参数加上双引号);'#'的转换是在预处理期实现的,所以只在宏定义中无效;编译器不晓得'#'的转换作用用法: #define STRING(s) #sprintf("%s\n", STRING(hello world));单步编译:gcc -E test.c -o test.i两头后果:printf("%s\n", "hello world");能够应用#+函数名,在调用时把函数名打印进去: #define CALL(f, p) (printf("call function: %s\n", #f), f(p))void func(){ printf("function output");}int main(){ CALL(f, 1); // C语言中如果不写参数列表,则承受任意多参数 return 0;}2、'##''##'运算符用于在预处理期粘连两个字符(拼接字符)'##'的拼接作用是在预处理期实现的,因而只在宏定义中无效、编译器不晓得'##'的拼接作用用法: #define CONNECT(a, b) a##bint CONNECR(a, 1); // int a1;a1 = 2;工程中能够用'##'疾速定义构造体(定义不同的类等) // 在C语言中应用构造体必须带上struct关键字,就能够用上面的宏封装下typedef,// 而后就能够把struct当成一个类型来用#define STRUCT(type) typedef strtuct __tag_##type type; \ struct __tag_##typeSTRTUCT(Student){ char* name; int id;};int main(){ Student s; s.name = "ss"; s.id = 1; printf("name: %s, id: %d\n"), s.name, s.id); retrun 0;}本文总结自“狄泰软件学院”唐佐林老师《C语言进阶课程》。如有错漏之处,恳请斧正。 ...

December 25, 2021 · 1 min · jiezi

关于c:C进阶24pragma分析

Summary1)#pragma 用于 批示编译器 实现一些特定的动作;#pragma 所定义的很多批示字是编译器特有的,所以在不同的编译器间是不可移植的 预处理器将疏忽它不意识的#pragma指令不同的编译器可能以不同的形式解释同一条#pragma指令个别用法:#pragma parameter ,不同的parameter参数语法和意义各不相同。2)#pragma message在编译时输入信息到编译输入窗口;和#error、#warning不同,#pragma message仅仅示意一条提示信息,不代表谬误。(vc、bcc和gcc三款编译器行为不同) 3)#pragma once用于保障头文件只被编译一次; #pragma once是编译器相干的,不肯定被反对。(vc和gcc反对,bcc不反对) 4)#ifndef...#define...#endif也能够用来避免头文件被反复蕴含,和#pragma once有何不同? #ifndef形式是C语言反对的,用在各个编译器都能够;如果一个.h被include了n次,预编译器就会判断n次这个头文件是否曾经蕴含了。#pragma once形式是编译器相干的,不肯定所有编译器都反对;预编译器只会解决一次,前面不再判断。5)什么是内存对齐? 不同类型的数据在内存中依照肯定的规定排列,不肯定是程序的一个接一个的排列6)为什么须要内存对齐? CPU对内存的读取不是间断的,而是分成块读取的,块的大小只能是2的幂,1、2、4、8...字节当读取操作的数据未对齐,则须要两次总线周期来拜访内存,因而性能会大打折扣某些硬件平台只能从规定的绝对地址处读取特定类型的数据,否则会产生硬件异样7)编译器默认的对齐形式为4字节对齐, #pragma pack(n) 能够调整编译器的默认对齐形式(vc和bcc编译器反对8字节对齐,然而gcc不反对) 8)内存对齐的规定: ·#pragma剖析#pragma 用于 批示编译器 实现一些特定的动作;#pragma 所定义的很多批示字是编译器特有的,所以在不同的编译器间是不可移植的 预处理器将疏忽它不意识的#pragma指令不同的编译器可能以不同的形式解释同一条#pragma指令个别用法:#pragma parameter ,不同的parameter参数语法和意义各不相同。1、#pragma messagemessage参数在大多数的编译器中都有类似的实现message参数在编译时输入音讯到编译输入窗口中message用于条件编译中可提醒代码的版本信息 #include <stdio.h>#if defined(ANDROID20) #pragma message("Compile Android SDK 2.0...") #define VERSION "ANDROID 2.0"#elif defined(ANDROID30) #pragma message("Compile Android SDK 3.0...") #define VERSION "Android 3.0"#elif defined(ANDROID40) #pragma message("Compile Android SDK 4.0...") #define VERSION "Amdroid 4.0"#else #error Compile version is not provided! #endifint main(){ printf("%s\n", VERSION); return 0;}不同编译器的编译后果: bcc编译器:bcc32 -DANDROID30 test.c 编译输入:Compile Android SDK 3.0... vc编译器:cl -DANDROID30 test.c 编译输入:Compile Android SDK 3.0... gcc编译器:gcc -DANDROID30 test.c 编译输入:note: #pragma message: Compile Android SDK 4.0...三款编译器的输入阐明:#pragma message会输入提示信息,然而行为类似,可能具体实现不同单步编译的两头文件: gcc -DANDROID30 -E test.c -o test.i# 12 "test.c"#pragma message("Compile Android SDK 3.0...")# 12 "test.c"# 20 "test.c"int main(){ printf("%s\n", "Android 3.0"); return 0;}留神:和#error、#warning不同,#pragma message仅仅代表一条编译信息,不代表程序谬误。 ...

December 23, 2021 · 2 min · jiezi

关于c:C进阶error和line使用分析

Summary1)#error用于生成一个编译谬误信息;#warning用于生成一个编译正告信息; 2)编译过程中的任何错误信息意味着无奈生成最终的可执行程序 3)语法:#error/#warning message,message不须要用双引号突围 4)#line用于指定后续代码的起始行号和文件名 5)语法:#line line filename filename可胜率,是个字符串(双引号) ·#error和#line剖析1、#error和#warning#error用于生成一个编译谬误信息;#warning用于生成一个编译正告信息; #error是一种预编译器批示字,可用于提醒编译条件是否满足。留神:编译过程中的任何错误信息意味着无奈生成最终的可执行程序语法:#error message,message不须要用双引号突围 #ifndef __cplusplus #error This file should be processed with C++ compiler.#endif应用gcc编译器编译:gcc test.c输入:test.c 4: error: #error This file should be processed with C++ compiler.不会生成可执行程序应用g++编译器编译:g++ test.c能够生成可执行程序剖析:__cplusplus是C++编译器里特有的宏,应用gcc时,无奈辨认这个宏, 因而输入了一条错误信息,并且因为存在错误信息,可执行程序无奈生成;应用g++时,就会跳过该段预处理。#ifndef __cplusplus #warning This file should be processed with C++ compiler.#endif应用gcc编译器编译:gcc test.c输入:test.c 4: warning: #warning This file should be processed with C++ compiler.尽管提醒了正告,然而会生成可执行程序2、#line#line 用于强制指定新的行号和编译文件名,并对源程序的代码从新编号;实质重定义__LINE__和__FILE__。用法:#line number filename (filename可省略) #line 1 "delphi.c" : 指定以后申明处的下一行为第1行,指定以后文件名为"delphi.c"背景:最开始大家都把代码写在一个文件里,比方3个开发同时实现了一个.c文件,这时候出错了就不好定位是谁写的代码出问题了。所以就用#line这个预处理批示字,来指明每一段代码的行号和文件名。下次出问题报错,就晓得是谁的代码写错了。 本文总结自“狄泰软件学院”唐佐林老师《C语言进阶课程》。如有错漏之处,恳请斧正。 ...

December 21, 2021 · 1 min · jiezi

关于c:C进阶22条件编译分析

Summary1)条件编译的行为相似于C语言中的if else;条件编译是预编译批示命令,用于管制是否编译某段代码; 2)预编译器依据条件编译指令有抉择的删除代码,所以编译器不晓得代码分支的存在 3)if else在运行期进行分支判断,肯定会被编进指标代码;条件编译指令在预编译期进行分支判断,可能产生不同的代码段,因而编进指标代码的代码段不确定 4)能够通过命令行定义宏:gcc -Dmacro=val file.c或gcc -Dmacro file.c 5)#include 实质 是将曾经存在的文件内容插入到以后文件中;#include的间接蕴含同样会产生嵌入文件内容操作。条件编译指令#ifndef _FILE_H_ #define _FILE_H #endif能够解决这种头文件反复蕴含的谬误。 6)条件编译指令只是能够在同一个.c文件中,避免反复蕴含;如果头文件中有了符号的定义,然而在一个工程的不同c文件里都进行了include,这时候编译这两个文件也会有反复定义的谬误(因为两份include在各自的c文件里都定义了一个global,在同一个全局作用域里定义了同名的symbol)。所以,头文件中只申明、不定义! 7)工程中的条件编译次要用于:不同的产品线共用一份代码;辨别编译产品的调试版和公布版 条件编译剖析条件编译的行为相似于C语言中的if...else...;条件编译是预编译批示命令,用于管制是否编译某段代码; 1、条件编译于if...else的区别预编译器依据条件编译指令有抉择的删除代码,所以编译器不晓得代码分支的存在if...else语句在运行期进行分支判断;条件编译指令在预编译期进行分支判断能够通过命令行定义宏:gcc -Dmacro=val file.c或者gcc -Dmacro file.c#define C1int main(){ #if (C==1) printf("if true\n"); #else printf("if false\n"); #endif return 0;}gcc -E test.c -o test.i// 单步编译后失去的两头文件# 1 "test.c"# 1 "<built-in>"# 1 "<command-line>"# 1 "test.c"int main(){ printf("if true\n"); return 0;}剖析: 通过预编译期的解决后,失去的两头文件中#if #else #endif都被删掉了,这也阐明了下面的预编译器依据条件编译指令有抉择的删除代码,所以编译器在拿到两头.i文件后,基本就不晓得这些代码分支的存在。也阐明,#if #else #endif是在预编译期进行判断的,而if else是在运行期才会判断// 上述代码中去掉#define C 1// 应用命令来定义宏gcc -DC=1 test.c编译后的运行后果为:if truegcc -DC test.cgcc -DC test.c编译后的运行后果为:if true应用#ifdef #else #endif进行预编译分支判断: ...

December 19, 2021 · 1 min · jiezi

关于c:libevent学习使用1

根本应用办法libevent是一个应用事件驱动模型的网络网络库,网络开发,能够通过应用这个库,非常简单、清晰的代码做出一个反对I/O复用的程序。工作中须要应用到此库,所以记录一下学习进度。 根本应用能够参考源码的sample/目录下的应用示例,依据示例名称,我首先看一下 hello-workd.c 这个程序:代码不少,然而单个函数拆分来看,还是分清晰的。 首先是main 函数中: //...... base = event_base_new(); //...... listener = evconnlistener_new_bind(base, listener_cb, (void *)base, LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1, (struct sockaddr*)&sin, sizeof(sin)); //...... /// 注册了一个信号事件,该事件处理函数 signal_cb 解决的Ctrl+C信号 signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base); if (!signal_event || event_add(signal_event, NULL)<0) { fprintf(stderr, "Could not create/add a signal event!\n"); return 1; } /// 开启工夫轮询 event_base_dispatch(base); /// 进行程序应用资源 evconnlistener_free(listener); event_free(signal_event); event_base_free(base);首先调用 event_base_new 创立了一个 event_base 构造体,也不晓得是干嘛的,然而并没有给他提供任何网络相干的参数,临时先不论它。之后调用了 evconnlistener_new_bind 函数,给他传入了网络的sockaddr构造信息,联合文件名看来就是在这里开始创立套接字和监听了。进入头文件listener.h 中也能看到对于该函数的介绍: /** Allocate a new evconnlistener object to listen for incoming TCP connections on a given address. @param base The event base to associate the listener with. event 会和 event_base 关联 @param cb A callback to be invoked when a new connection arrives. If the callback is NULL, the listener will be treated as disabled until the callback is set. 链接来的socket的处理函数 @param ptr A user-supplied pointer to give to the callback. 参数指针 @param flags Any number of LEV_OPT_* flags @param backlog Passed to the listen() call to determine the length of the acceptable connection backlog. Set to -1 for a reasonable default. @param sa The address to listen for connections on. @param socklen The length of the address. */能够看出 listener_cb 是解决链接客户端的socket,LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE能够依据listen.h中找到解释,设置了socket地址的可重用和敞开时开释, sa 是地址信息。 ...

December 18, 2021 · 2 min · jiezi

关于c:C进阶21宏定义与使用分析

Summary1)#define是预处理器解决的单元实体之一,在预编译期进行文本替换 2)#define定义的宏能够呈现在程序的任意中央,定义之后的代码都能够应用 3)#define能够定义宏常量,实质上是字面量 4)define能够定义表达式,应用上相似函数;性能可能更弱小(类型能够作为参数、求数组大小);更容易出错(当和其余运算混合在一起时) 5)宏因为是间接文本替换,所以没有任何的调用开销;宏表达式里不能呈现递归;宏被预处理器解决,所以编译器不晓得宏的存在,天然宏也不会有作用域的概念,作用域是针对变量和函数的。 6)罕用的预约义宏 宏含意示例__FILE__被编译的文件名file1.c__LINE__以后行号25__DATE__编译时的日期Jan 31 2012__TIME__编译时的工夫17:01:01__STDC__编译器是否遵循规范C标准1宏定义与应用剖析#define是预处理器解决的单元实体之一#define定义的宏能够呈现在程序的任意地位#define定义之后的代码都能够应用这个宏 1、#define定义的宏常量#define定义的宏常量能够间接应用,实质为字面量(不会占用内存,字符串字面量会存在只读存储区) // test.c中 上面的宏定义正确么?#define ERROR -1#define PATH1 "D:\test\test.c"#define PATH2 D:\test\test.c#define PATH3 D:\test\test.cint main(){ int i = ERROR; char* p1 = PATH1; char* p2 = PATH2; char* p3 = PATH3; return 0;}单步编译gcc -E test.c -o test.i ==> 预编译,生成两头文件.igcc -S test.i -o test.s ==> 编译,生成汇编文件.s剖析:在第一步预编译阶段,解决define并生成.i文件,这时候不会出错;下一步编译阶段,将两头文件转换为汇编文件时,就会报错。起因在于:在预编译的阶段,仅仅是做文本替换,没有语法查看;到了编译阶段,会对替换后的.i文件进行语法查看,再生成汇编文件,这时候语法查看就出错了。 2、#define定义的表达式#define表达式的应用相似函数调用#define表达式能够比函数更弱小#define表达式比函数更易出错 #define SUM(a, b) (a) + (b)#define MIN(a, b) ((a) < (b) ? (a) : (b))#define DIM(a) sizeof(a) / sizeof(*a)int main(){ int a = 1; int b = 3; int c[2] = {0}; // expected: 4, 1, 2 printf("SUM(a, b) = %d\n", SUM(a, b)); printf("MIN(a, b) = %d\n", MIN(a, b)); printf("size of array = %d\n", DIM(c)); // unexpected: 3 printf("unexpected: %d", MIN(++a, b)); // 冀望失去++a和b中的较小的值:2 return 0;}剖析: ...

December 17, 2021 · 1 min · jiezi

关于c:C进阶20链接过程简介

Summary1)链接的定义:将指标文件最终链接为可执行程序 2)链接的2种形式: 动态链接:指标文件会被间接*链接*进可执行程序。slib.a被删掉后,程序仍旧能够运行动静链接:程序启动后才动静加载指标文件。dlib.so被删掉后,程序无奈运行3)动态链接和动静链接形式的抉择: 动态链接:实用于比较简单的程序,开发进去不须要变动的,比方纯本地的记事本这种;把所有指标文件都编到可执行程序里,可能会导致可执行程序很大。动静链接:一个大型软件的各个模块,如果采纳动静库的模式,哪个模块须要更新了,只须要批改这个模块,而后把dlib.so传到服务器上。用户在应用软件时,间接去服务器上拿这一个库更新下就能够了,而不须要更新整个程序。链接过程简介问题:工程里的每个.c源文件在编译后都会生成指标文件.o,那这些.o文件怎么生成最终的可执行程序.out呢? 答:链接器的次要作用是把各个模块间互相援用的局部解决好,使得各个模块之间能失常的连接。 1、动态链接链接器在链接时将库的内容间接退出到可执行程序中动态库的创立和应用1)生成动态库指标文件:gcc -c slib.c -o slib.o2)生成动态库:ar -q slib.a slib.o (输入:ar:creating slib.a;ar指的是archive,把前面列出的所有指标文件全都打包进slib.a中)3)应用动态库编译:gcc 20-1.c slib.a -o 20-1.out (应用动态库进行编译)2、动静链接可执行程序在运行时才动静加载库进行链接(运行时才去找我须要的symbol)库的内容不会进入到可执行程序中// dlib.cchar* name(){ return "Dynamic Lib";}int add(int a, int b){ return a+b;}// 20-2.c#include <stdio.h>#include <dlfcn.h>int main(){ void* pdlib = dlopen("./dlib.so", RTLD_LAZY); // pdlib指向了目录下dlib.so这个动静库 // 这个关上就相当于一个加载到内存里的指针 char* (*pName)(); // 定义函数指针 int (*pAdd)(int, int); if(NULL != pdlib) { pName = dlsym(pdlib, "name"); // 查找pdlib指向的动静库里的函数 pAdd = dlsym(pdlib, "add"); if(NULL != pName && NULL != pAdd) { printf("Name: %s\n", pName()); printf("Ret: %d\n", pAdd(2, 3)); } dlclose(pdlib); // 敞开pdlib指向的动静库 } else { printf("Cannot open dynamic lib..."); }}// linux命令gcc -shared dlib.c -o dlib.so : 创立了动静库dlib.sogcc 20-2.c -ldl -o a.out : 应用动静库创立了可执行程序a.out./a.out : 执行可执行程序留神:-ldl通知编译器,这个程序用动静库的形式来编译,咱们的程序依赖动静库。如果动静库dlib.so删掉了,这个程序就运行不起来了,输入cannot open,因为a.out每次执行时须要去动静库里找symbol的(我要用啥,我每次得去你的仓库里拿),库都没了,天然找不到了。 ...

December 15, 2021 · 1 min · jiezi

关于c:01-OCFS2文件系统磁盘布局分析

文件系统实质上是把文件存入磁盘,因而,了解文件系统的磁盘整体布局对于了解一款文件系统十分的重要,文件系统的所有性能都是围绕磁盘布局和对其治理开展的,上面咱们一起看一下OCFS2集群文件系统的磁盘整体布局。一、格式化format:mkfs.ocfs2 -b 4K -C 1M -N 32 -J size=128M -L "xxx" -T vmstore --fs-features=indexed-dirs,refcount --cluster-stack=o2cb --cluster-name=ocfs2 fs.img 格式化参数解释: -b, --block-size block-size 文件系统执行IO的最小单元,本例取 block 4KB=4096=2^10-C, --cluster-size cluster-size 为文件数据调配空间的最小单元,本例取 cluster 1MB=2^20-N, --node-slots number-of-node-slots 节点槽位,指向一系列的系统文件,每个槽位被一个节点惟一应用。槽位的个数示意该volume可同时被多少个节点mount。-J, --journal-options options OCFS2采纳预写日志WAL(Write-Ahead Log),应用了JBD2,用户可配置,依据文件系统类型和卷大小决定,默认值:datafiles类型64MB,vmstore类型128MB,mail类型256MB-L, --label volume-label 对卷做标签,为了方便管理。-T filesystem-type Valid types are mail, datafiles and vmstore.mail:用作邮件服务器存储,将大量的元数据变为大量的小文件,应用大一点的日志journal比拟无益。datafiles:倡议较少地全副调配大文件,要求较少的元数据扭转,因而,应用大一点的日志journal有益。vmstore:正如名字所示,被稠密调配大文件的虚拟机镜像--fs-features=[no]sparse...  指定使能或禁用某些个性,比方:稠密文件、非写入范畴、备份超级块--fs-feature-level=feature-level Valid values are max-compat, default and max-features. 默认反对稠密文件、非写入范畴、内联数据。查看根目录和系统目录通过debugfs.ocfs2,能够看到系统文件,本例格式化指定 -N 32,因而,一些带slot号的系统文件,如:local_allock:0000~0031,如下截图仅显示局部,其余已将其省略,不影响剖析。 通过格式化的参数,能够失去如下根底数据信息,这些信息能够不便的进行计算。 1 block 4KB = 4096 = 2^10 1 cluster 1MB = 2^20 1 cluster = 256 blocks = 2^8二、SuperBlock对于一个文件系统而言SuperBlock是最重要的,它形容了一个文件系统的根本数据信息,含有许多重要的要害信息,文件系统被mount操作后,首先要读取SuperBlock。格式化后,能够看到SuperBlock的信息如下: ...

December 10, 2021 · 3 min · jiezi

关于c:CPT109-C-Programming

CPT109 C Programming and Software Engineering 1 – ASSESSMENT 3Assessment Number 3Contribution to Overall Marks 35%Issue Date 08/11/2021Submission Deadline 17/12/2021 at 17:00 (5pm)Assessment ObjectiveThis assessment aims to evaluate students’ ability to develop a significant software solution to a realworldproblem by working as a member of a team. Your team will be given a vague specification andis expected to deliver a software product in the C programming language, which meets thespecifications before the due date. This size and type of the project is suitable for development inmodular format and so teams are encouraged to devise program structures that allow various parts ofthe code to be developed independently by each team member. Being a team player means you areexpected not only to apply the knowledge gained during the lectures, laboratory classes andassignments to specify, design, implement, test and document your own code, but also to cooperatewith your teammates so that the whole project will be delivered on time with good quality.GroupingThere are 360 students enrolled in this module, and you will be divided into groups consisting of 5students (i.e. 72 groups). Groups will be formed in two stages as follows: Firstly, students will begiven the option to choose their own group members. Students failing to form a group will then berandomly assigned to a group. Randomly formed groups will contain students with a range of abilitybased on their performance in previous assignments. Each group will then be randomly assigned oneof 5 projects. Students wishing to form their own group should submit a hardcopy of the formprovided (The group formation form is part of the Assessment 3 download package) having alldetails filled in and having been signed by all group members.Final DeliverablesEach group should submit the following (only 1 submission per group): ...

December 9, 2021 · 10 min · jiezi

关于c:深度剖析C语言知识体系-原理实践一课带你吃透C语言jfgjdgjd

download:深度分析C语言常识体系 原理+实际,一课带你吃透C语言结构字符串 你会常常需要打印字符串。要是有很多变量,防止上面这样: name = "Raymond" age = 22 born_in = "Oakland, CA" string = "Hello my name is " + name + "and I'm " + str(age) + " years old. I was born in " + born_in + "." print(string)额,这看起来多乱呀?你能够用个丑陋简洁的办法来代替, .format 。 这样做: 前言去年11月在PyCon China 2018 杭州站分享了 ,讲述了如何通过修改 Python 解释器达到加解密 Python 代码的目标。然而因为笔者迁延症发生,一直没有及时整顿成文字版,现在终于战胜了它,才有了本文。 本文将首先介绍下现有源码加密打算的思路、方法、长处与不足,进而介绍如何通过定制 Python 解释器来达到更好地加解密源码的目标。 现有加密打算因为 Python 的动静个性和开源个性,导致 Python 代码很难做到很好的加密。社区中的一些声音认为这样的限度是事实,应该通过法律手段而不是加密源码达到商业保护的目标;而还有一些声音则是不论如何都心愿能有一种手段来加密。于是乎,人们想出了各种或加密、或混淆的打算,借此来达到保护源码的目标。 常见的源码保护手段有如下几种: 发行 .pyc 文件代码混淆使用 py2exe使用 Cython上面来简略说说这些打算。 发行 .pyc 文件思路大家都知道,Python 解释器在执行代码的过程中会首先生成 .pyc 文件,而后解释执行 .pyc 文件中的内容。当然了,Python 解释器也能够间接执行 .pyc 文件。而 .pyc 文件是二进制文件,无奈间接看出源码内容。如果发行代码到客户环境时都是 .pyc 而非 .py 文件的话,那岂不是能达到保护 Python 代码的目标? ...

December 8, 2021 · 2 min · jiezi

关于c:闲聊C语言结构体

构造体是 C 语言次要的自定义类型计划,这篇就来认识一下构造体。一、构造体的状态C源程序(struct.c): #include <stdio.h>typedef struct{ unsigned short int a; unsigned short int b;}Data;int main(){ Data c, d; c.a = 1; c.b = 2; d = c; printf("d.a:%d\nd.b:%d\n", d.a, d.b); return 0;}赋值局部翻译后: movw $1, 28(%esp) # c.a = 1 movw $2, 30(%esp) # c.b = 2 movl 28(%esp), %eax # movl %eax, 24(%esp) # d = c 能够看出: c.a 是在 28(%esp) 之后的2个字节c.b 是在 30(%esp) 之后的2个字节c 是 28(%esp) 之后的4个字节d 是 24(%esp) 之后的4个字节不得不感叹名字(构造体名字、子元素名字)再一次被抛弃了,子元素名代表的是绝对于构造体的偏移。 ...

December 8, 2021 · 1 min · jiezi

关于c:veth原理两个容器通过veth通信时数据包的收发路径

基于linux内核5.4.54veth是一个虚构网络设备,是通过linux内核网络设备驱动实现的 /* veth设施在内核上注册的调用办法 */static const struct net_device_ops veth_netdev_ops = { .ndo_init = veth_dev_init, /* 初始化设施 */ .ndo_open = veth_open, /* 关上设施 */ .ndo_stop = veth_close, /* 敞开设施 */ .ndo_start_xmit = veth_xmit, /* 传输数据包(重要) */ .ndo_get_stats64 = veth_get_stats64, /* 拷贝硬件统计计数到用户空间 */ .ndo_set_rx_mode = veth_set_multicast_list, /* 外面是空函数,骗人的 */ .ndo_set_mac_address = eth_mac_addr, /* 批改MAC地址 */#ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = veth_poll_controller, /* 外面是空函数,骗人的 */#endif .ndo_get_iflink = veth_get_iflink, /* 获取设施的iflink值(应该是编号) */... .ndo_bpf = veth_xdp, /* 设置或查问设施上与XDP相干的状态,以及治理BPF offload。 */ .ndo_xdp_xmit = veth_xdp_xmit, /* 传输XDP数据包 */};通过veth将两个容器连接起来 ...

December 3, 2021 · 1 min · jiezi

关于c:单机容器网络

基于linux内核5.4.54昨天分享了veth的原理:veth原理----两个容器通过veth通信时数据包的收发门路个别状况容器间接不会通过veth间接通信,会通过docker0网桥通信明天剖析容器通过veth和docker0网桥的通信门路 单机容器网络结构在宿主机上通过docker创立两个容器时会主动生成如图所示的网络结构 在宿主机上会生成一个docker0网桥容器1和docker0网桥之间通过veth相连,容器2一样简略看一下Namespace网络设备的Namespace:网络设备注册时,会通过net_device->nd_net(网络设备构造体字段)设置Net Namespace。 剖析结构图设施的Namespace:veth0属于Namespace1;veth1属于Namespace2;eth0,docker0,docker0上的两个veth设施属于Host Namespace数据包的Namespace:数据包的Namespace由skb_buff->dev->nd_net(数据包目标设施的Namespace)决定 过程的Namespace:通过clone()创立过程时会通过task_struct->nsproxy(过程构造体字段)为过程设置Namespace,nsproxy->net_ns决定过程的Net Namespace /* nsproxy构造体 其中蕴含了各种命名空间隔离和Cgroup,当前有工夫会多理解 */struct nsproxy { atomic_t count; struct uts_namespace *uts_ns; struct ipc_namespace *ipc_ns; struct mnt_namespace *mnt_ns; struct pid_namespace *pid_ns_for_children; struct net *net_ns; struct cgroup_namespace *cgroup_ns;};Socket套接字的Namespace过程创立Socket时,会设置sock->sk_net为current->nsproxy->net_ns,行将以后过程的Net Namespace传递给sock套接字。 剖析两种状况1. 容器1通过网桥向容器2发送数据包收发门路:过程(容器1)|--通过socket零碎调用进入内核,通过的是Namespace1的网络协议栈kernel层: 创立skb构造体,从用户空间拷贝数据到内核空间TCP/UDP封包IP封包,跑Namespace1的路由和netfilter|--出协定栈进入网络设备调用网络设备驱动的传输数据包函数|veth_xmit: veth驱动注册的传输函数 | veth_forward_skb | __dev_forward_skb: 革除 skb 中可能影响命名空间隔离的所有信息 | 并且会更新数据包要到的网络设备(skb->dev),由veth0改为docker-veth0 | 数据包要跑的协定栈(network namespace)由skb->dev的nd_net字段决定 | XDP钩子点 | netif_rx | netif_rx_internal: cpu软中断负载平衡 | enqueue_to_backlog: 将skb包退出指定cpu的input_pkt_queue队尾 queue为空时激活网络软中断, queue不为空不须要激活软中断,cpu没清空队列之前 会主动触发软中断 每个cpu都有本人的input_pkt_queue(接管队列,默认大小1000,可批改),和process_queue(解决队列),软中断处理函数解决实现process_queue中的所有skb包之后,会将将input_pkt_queue拼接到process_queue input_pkt_queue和process_queue是cpu为非NAPI设施筹备的队列,NAPI设施有本人的队列 始终到这里,数据包门路和veth文档中的两个veth通信的发送阶段是完全一致的,docker0网桥解决数据包次要在__netif_receive_skb_core中cpu解决网络数据包过程:do_softirq()|net_rx_action: 网络软中断处理函数 | napi_poll | n->poll: 调用目标网络设备驱动的poll函数 | veth设施没有定义poll,调用默认poll函数-process_backlog | process_backlog: cpu循环从process_queue中取出skb解决,最多解决300个skb, | 解决队列清空后,拼接input_pkt_queue到process_queue队尾 | __netif_receive_skb | ... | __netif_receive_skb_core数据包解决代码剖析:/** __netif_receive_skb_core代码剖析* 代码做了很多删减,剩下了网桥的解决和数据包传递给下层解决的局部* 其余很多局部例如vlan,xdp,tcpdump等代码删去了*/static int __netif_receive_skb_core(struct sk_buff **pskb, bool pfmemalloc, struct packet_type **ppt_prev){ struct packet_type *ptype, *pt_prev; rx_handler_func_t *rx_handler; struct sk_buff *skb = *pskb; struct net_device *orig_dev; bool deliver_exact = false; int ret = NET_RX_DROP; __be16 type; /* 记录skb包目标设施 */ orig_dev = skb->dev; /* 设置skb包的协定头指针 */ skb_reset_network_header(skb); if (!skb_transport_header_was_set(skb)) skb_reset_transport_header(skb); skb_reset_mac_len(skb); pt_prev = NULL;another_round:... /** * skb包的目标设施是docker-veth0,veth作为了bridge的一个接口 * docker-veth0在注册时会设置rx_handler为网桥的收包函数br_handle_frame * 黄色处代码为调用bridge的br_handle_frame */ rx_handler = rcu_dereference(skb->dev->rx_handler); if (rx_handler) { ... switch (rx_handler(&skb)) { case RX_HANDLER_CONSUMED: /* 已解决,无需进一步解决 */ ret = NET_RX_SUCCESS; goto out; case RX_HANDLER_ANOTHER: /* 再解决一次 */ goto another_round; case RX_HANDLER_EXACT: /* 准确传递到ptype->dev == skb->dev */ deliver_exact = true; case RX_HANDLER_PASS: break; default: BUG(); } }... /* 获取三层协定 */ type = skb->protocol; /* * 调用指定协定的协定处理函数(例如ip_rcv函数) 把数据包传递给下层协定层解决 * ip_rcv函数是网络协议栈的入口函数 * 数据包达到这里会通过netfilter,路由,最初被转发或者发给下层协定栈 */ deliver_ptype_list_skb(skb, &pt_prev, orig_dev, type, &orig_dev->ptype_specific);... if (pt_prev) { if (unlikely(skb_orphan_frags_rx(skb, GFP_ATOMIC))) goto drop; *ppt_prev = pt_prev; } else {drop: if (!deliver_exact) atomic_long_inc(&skb->dev->rx_dropped); else atomic_long_inc(&skb->dev->rx_nohandler); kfree_skb(skb); ret = NET_RX_DROP; }out: *pskb = skb; return ret;}网桥解决代码剖析: ...

December 3, 2021 · 2 min · jiezi

关于c:PTA-611-求自定类型元素序列的中位数-25-分

本题要求实现一个函数,求N个汇合元素A[]的中位数,即序列中第⌊(N+1)/2⌋大的元素。其中汇合元素的类型为自定义的ElementType 函数接口定义:ElementType Median( ElementType A[], int N );其中给定汇合元素寄存在数组A[]中,正整数N是数组元素个数。该函数须返回N个A[]元素的中位数,其值也必须是ElementType类型。 裁判测试程序样例:#include <stdio.h>#define MAXN 10typedef float ElementType;ElementType Median( ElementType A[], int N );int main (){ ElementType A[MAXN]; int N, i; scanf("%d", &N); for ( i=0; i<N; i++ ) scanf("%f", &A[i]); printf("%.2f\n", Median(A, N)); return 0;}/* 你的代码将被嵌在这里 */输出样例:3 12.3 34 -5输入样例:12.30做法一应用希尔排序(for) ElementType Median( ElementType A[], int N ) { ElementType temp; for (int gap = N / 2; gap > 0; gap /= 2) { for (int i = gap; i < N; i++) { for (int j = i - gap; j >= 0 && A[j] > A[j+gap] ; j-=gap) { temp = A[j]; A[j] = A[j+gap]; A[j+gap] = temp; } } } return A[N/2];}(18条音讯) 6-11 求自定类型元素序列的中位数 (25 分)_LIQIANDI的博客-CSDN博客 ...

December 2, 2021 · 1 min · jiezi

关于c:PTA-69-统计个位数字-15-分

本题要求实现一个函数,可统计任一整数中某个位数呈现的次数。例如-21252中,2呈现了3次,则该函数应该返回3 函数接口定义:int Count_Digit ( const int N, const int D );其中N和D都是用户传入的参数。N的值不超过int的范畴;D是[0, 9]区间内的个位数。函数须返回N中D呈现的次数。 裁判测试程序样例:#include <stdio.h>int Count_Digit ( const int N, const int D );int main(){ int N, D; scanf("%d %d", &N, &D); printf("%d\n", Count_Digit(N, D)); return 0;}/* 你的代码将被嵌在这里 */输出样例:-21252 2输入样例:3做法一如果是正数,须要转换为负数解决将数字拆开放入数组应用 for 遍从来判断是否有雷同的数字int Count_Digit ( const int N, const int D ) { int arr[10] = {0}; int num = N; int count = 0; int numCount = 0; if (num < 0) { num = -num; } while (num >= 10) { arr[count++] = num % 10; num /= 10; } arr[count] = num; for (int i = 0; i <= count; i++) { if (arr[i] == D) { numCount++; } } return numCount;}做法二如果是正数,须要转换为负数解决应用 do ... while 循环先判断一次,能够解决传入值为 0 的问题,当 num 为 0 时,count = 1循环体中将 num 拆开,每拆下来一个数字就比拟是否雷同,如果雷同,count 加 1int Count_Digit ( const int N, const int D ) { int num = N; int count = 0; if (num < 0) { num = -num; } do { if (D == num % 10) { count++; } num /= 10; } while (num > 0); return count;}

December 2, 2021 · 1 min · jiezi

关于c:时间相关函数

linux工夫函数有不少,平时用的也比拟多,然而这些函数常常忘了,故记录下来,留作当前编程查问之用。 time函数#include <time.h>time_t time(time_t * t)此函数会返回从公元1970年1月1日的UTC工夫从0时0分0秒算起到当初所通过的秒数。如果t 并非空指针的话,此函数也会将返回值存到t指针所指的内存.产生谬误返回-1. clock_gettime#include <sys/time.h>int clock_gettime(clockid_t clock_t,struct timespec * tsp);此函数用于获取指定的时钟工夫.罕用如下4种时钟:CLOCK_REALTIME 统以后工夫,从1970年1.1日算起CLOCK_MONOTONIC 零碎的启动工夫,不能被设置CLOCK_PROCESS_CPUTIME_ID 本过程运行工夫CLOCK_THREAD_CPUTIME_ID 本线程运行工夫.胜利返回0,产生谬误返回-1。 struct timespec 的构造如下: struct timespec { time_t tv_sec; // seconds long tv_nsec; // and nanoseconds};当clockid_t为CLOCK_REALTIME时,clock_gettime函数跟time函数性能相似。 gettimeofday函数#include <sys/time.h>int gettimeofday (struct timeval * tp, void * tzp);gettimeofday 返回胜利时函数将间隔1970.1.1 的工夫存储在指针tp指向的地址中,struct timeval 的构造如下。tzp 依赖于相干unix平台实现来代表时区。返回值总是返回0. struct timeval { time_t tv_sec; // seconds long tv_usec; // microseconds};localtime和gmtime#include <time.h>struct tm * gmtime(const time_t * calptr);struct tm * localtime(const time_t * calptr);gmtime和localtime 两个函数将日历工夫转换为合成工夫,并将其存在struct tm 构造中. ...

December 1, 2021 · 1 min · jiezi

关于c:编程艺术剖析-darknet-loadweights-接口

 欢送关注我的公众号 [极智视界],回复001获取Google编程标准 O_o >_<  o_O O_o ~_~ o_O 本文剖析下 darknet load_weights 接口,这个接口次要做模型权重的加载。 1、darknet 数据加载流程   之前的文章曾经介绍了一下 darknet 指标检测的数据加载流程,并介绍了.data、.names 和 .cfg 的加载实现。   接下来这里 load_weights 接口次要做 .weights 模型权重的加载。 2、load_weights 接口   先来看一下接口调用: load_weights(&net, weightfile);   其中 net 为 network 构造体的实例,weightfile 为权重的文件门路,看一下 load_weights 的实现: /// parser.cvoid load_weights(network *net, char *filename){ load_weights_upto(net, filename, net->n);}   次要调用了 load_weights_upto 函数: /// parser.cvoid load_weights_upto(network *net, char *filename, int cutoff){#ifdef GPU if(net->gpu_index >= 0){ cuda_set_device(net->gpu_index); // 设置 gpu_index } #endif fprintf(stderr, "Loading weights from %s...", filename); fflush(stdout); // 强制马上输入 FILE *fp = fopen(filename, "rb"); if(!fp) file_error(filename); int major; int minor; int revision; fread(&major, sizeof(int), 1, fp); // 一些标记位的加载 fread(&minor, sizeof(int), 1, fp); fread(&revision, sizeof(int), 1, fp); if ((major * 10 + minor) >= 2) { printf("\n seen 64"); uint64_t iseen = 0; fread(&iseen, sizeof(uint64_t), 1, fp); *net->seen = iseen; } else { printf("\n seen 32"); uint32_t iseen = 0; fread(&iseen, sizeof(uint32_t), 1, fp); *net->seen = iseen; } *net->cur_iteration = get_current_batch(*net); printf(", trained: %.0f K-images (%.0f Kilo-batches_64) \n", (float)(*net->seen / 1000), (float)(*net->seen / 64000)); int transpose = (major > 1000) || (minor > 1000); int i; for(i = 0; i < net->n && i < cutoff; ++i){ // 辨认不同算子进行权重加载 layer l = net->layers[i]; if (l.dontload) continue; if(l.type == CONVOLUTIONAL && l.share_layer == NULL){ load_convolutional_weights(l, fp); } if (l.type == SHORTCUT && l.nweights > 0) { load_shortcut_weights(l, fp); } if (l.type == IMPLICIT) { load_implicit_weights(l, fp); } if(l.type == CONNECTED){ load_connected_weights(l, fp, transpose); } if(l.type == BATCHNORM){ load_batchnorm_weights(l, fp); } if(l.type == CRNN){ load_convolutional_weights(*(l.input_layer), fp); load_convolutional_weights(*(l.self_layer), fp); load_convolutional_weights(*(l.output_layer), fp); } if(l.type == RNN){ load_connected_weights(*(l.input_layer), fp, transpose); load_connected_weights(*(l.self_layer), fp, transpose); load_connected_weights(*(l.output_layer), fp, transpose); } if(l.type == GRU){ load_connected_weights(*(l.input_z_layer), fp, transpose); load_connected_weights(*(l.input_r_layer), fp, transpose); load_connected_weights(*(l.input_h_layer), fp, transpose); load_connected_weights(*(l.state_z_layer), fp, transpose); load_connected_weights(*(l.state_r_layer), fp, transpose); load_connected_weights(*(l.state_h_layer), fp, transpose); } if(l.type == LSTM){ load_connected_weights(*(l.wf), fp, transpose); load_connected_weights(*(l.wi), fp, transpose); load_connected_weights(*(l.wg), fp, transpose); load_connected_weights(*(l.wo), fp, transpose); load_connected_weights(*(l.uf), fp, transpose); load_connected_weights(*(l.ui), fp, transpose); load_connected_weights(*(l.ug), fp, transpose); load_connected_weights(*(l.uo), fp, transpose); } if (l.type == CONV_LSTM) { if (l.peephole) { load_convolutional_weights(*(l.vf), fp); load_convolutional_weights(*(l.vi), fp); load_convolutional_weights(*(l.vo), fp); } load_convolutional_weights(*(l.wf), fp); if (!l.bottleneck) { load_convolutional_weights(*(l.wi), fp); load_convolutional_weights(*(l.wg), fp); load_convolutional_weights(*(l.wo), fp); } load_convolutional_weights(*(l.uf), fp); load_convolutional_weights(*(l.ui), fp); load_convolutional_weights(*(l.ug), fp); load_convolutional_weights(*(l.uo), fp); } if(l.type == LOCAL){ int locations = l.out_w*l.out_h; int size = l.size*l.size*l.c*l.n*locations; fread(l.biases, sizeof(float), l.outputs, fp); fread(l.weights, sizeof(float), size, fp);#ifdef GPU if(gpu_index >= 0){ push_local_layer(l); }#endif } if (feof(fp)) break; } fprintf(stderr, "Done! Loaded %d layers from weights-file \n", i); fclose(fp);}   以上有几个点不容易看懂,如以下这段: ...

November 17, 2021 · 4 min · jiezi

关于c:C-语言为什么不会过时

本文整顿自网络 作者: 赵岩/Serdar等 01、为什么C语言不会过期评估任何一门编程语言,都是招人骂的。永远是这样。就像是春寒料峭的节令,街上穿棉袄和穿单衣的擦肩而过,单方肯定是同时在心里呈现了两个字:“傻逼!”这个在心理学上有个业余的名字:叫做“二逼”景象! 那我为啥还要做这个挨骂的事呢?作为《C语言点滴》《drop of knowledge of C++》书籍的作者,《C语言新思维,第二版》的译者(赵岩老师),我感觉我有责任零碎的介绍一下这本语言,他的特点,还有他的将来。这个问题对很多刚刚踏入程序猿这个行业的老手至关重要。因为他们有深深的担心,万一C语言就像Fortran那样过期了怎么办? 先上一个表,这个就是驰名的TIOBE语言排行榜。目前它是一个最权威的一个语言风行度的排行榜。 就在5月,时隔5年,C语言再次当先Java,荣登TIOBE编程语言排行榜第一! 排名前十的别离是: C,Java,Python,C++,C#,Visual Basic.NET,JavaScript,PHP,SQL和R。 有没有发现亮点?没错, 第一易主了,C 语言反超了 Java 。要晓得,C 语言上次第一还是在 5 年前,是什么起因让其“卷土重来”了呢? 时隔五年,C语言重回榜首。 据TIOBE CEO Paul Jansen 的猜想,“这听起来可能很不堪设想,然而某些编程语言的确能够从这种状况中受害。"嵌入式语言(C 和 C++ 等)越来越风行,因为它们被用于医疗设施软件中。 对所有的编程语言,他们的最初的目标其实就是两种:进步硬件的运行效率和进步程序员的开发效率。 遗憾的是,这两点是不可能并存的!你只能选一样。在进步硬件的运行效率这一方面,C语言没有竞争者!举个简略的例子,实现一个列表,C语言用数组int a[3],通过编译当前变成了(基地址+偏移量)的形式。对于计算机来说,没有运算比加法更快,没有任何一种办法比(基地址+偏移量)的存取方法更快。 C语言曾经把硬件的运行效率压缩到了极致。这种设计思维带来的问题就是易用性和安全性的缺失。例如,你不能在数组中混合保留不同的类型,否则编译器没有方法计算正确的偏移量。同时C语言对于谬误的偏移量也充耳不闻,这就是C语言中臭名远扬的越界问题。 C语言自夸的“置信程序员”都是丑陋的说辞,它的惟一目标就是快,要么飞速的运行,要么飞速的解体。C语言只关怀程序飞的高不高,不关怀程序猿飞的累不累。就是这样! 当初来看看那些非C的语言,他们的短处都在于进步程序员的开发效率上。或者反对动静的列表,或者反对平安的列表。然而退出任何的中间层,退出任何的平安测验,它不可能比(基地址+偏移量+无测验)的形式更快。这个世界上不存在“开发容易,运行快”的语言,开发容易毕竟来源于对底层的一层一层又一层的包装。 当初答复两个最广泛的问题:硬件这么便宜了,有必要让软件更快吗?有这种疑难的人大部分都是网吧的固定客户,他们了解的计算机只在电脑城,他们了解的计算只是游戏和播放硬盘中的小电影。不要玩个游戏开个挂就乐得不行不行的,别忘了还有全实景仿真,还有3D渲染,还有主动驾驶。 人在开车的时候,每秒要收集60个不同的物体,而后依据这60个物体的不同组合和反映来做20个最重要的决定。而后从这20多个决定当选一个执行。所以就算用上最快的硬件,主动驾驶当初还不敢说能像人那样开车。就算是主动驾驶胜利了,下一步还要主动航行呢?因为咱们老早就预言了:你咋不入地呢! 所以说:计算速度永远是不够的!因为新的利用会越来越简单,越来也实时。对了!我还忘了一个更重要的限度:计算的能耗!NASA飞行器上的CPU最多就是32位的,说进去你可能不信,国内空间站上没有一个CPU是64位的,我猜一个最次要的起因是航天员不爱看硬盘小电影吧。 另外一个风行的疑难是:我能够创造一种同样快的语言,然而没有C语言那么多的坑。想法是能够的,而且还真巧有这个语言,真巧它的名字叫D语言,真巧没有太多的人用!这是因为一个根本的事实。当初有太多,太多太多的C代码,他们大部分都在失常工作,就像Linux, Window, MacOS,Unix,Vxworks。你没有看错,这些操作系统的内核都是C,我尽管不确定C在Window中所占的比例,然而我置信微软的人不会傻到用C#去全副改写一个操作系统的内核。你想让这些人去用你的全新的语言,这就不是“有点”很傻,很天真了! 而且有些代码,咱们基本就不能改!NASA一个简略的5个CPU飞控软件编写结束后,要进行一种“全笼罩”测试。如果CPU A坏了会产生什么?如果CPU A,B坏了呢?如果CPU A,C坏了呢。。。。?如果你违心,你能够做个简略的数学组合。测试结束后,别说重写,就算加个正文都不行。因为主管payload的大妈会十分庄重的质问你,为什么你上报的货色数量减少了,然而品质没有减少?你须要和她具体的解释:硬件和软件是不同的,硬件是那种摸起来硬硬的货色,然而软件不是那种摸起来软软的货色。看着大妈鄙夷的眼神,这个时候你会十分悔恨本人手欠退出的哪一行正文。你还别不当真,这个是NASA的实在故事。 那为什么C语言还降落这么多呢?很简略,有些工作自身就不是C语言的。我上学的时候还用C语言编过窗口界面呢?而后很快微软的人就推出了MFC,就是一大堆宏把底层的C windowAPI包装了起来。 再起初这个技术也过期了。因为微软的人意识到,带有窗口的应用程序说到底不是C语言的本职工作,再这么一层一层包下去就有露馅的危险,于是他们创造了一个全新的语言C#来负责这个工作。 Java也是这样,突出网络,易用,平安,跨平台。无论是Java, c#还是python, 他们都无意避开进步硬件的运行效率这个问题,因为这个问题上没方法和C竞争,也无奈撼动Linux, Unix,GNU tool这些已有C代码的地位。剩下的就只是进步程序员的开发效率上大作文章。这对C语言是坏事,把本人不善长的货色去掉,让本人跑的更快! 随同着嵌入和实时零碎的衰亡,AI,机器人,主动驾驶等。这些都是C语言的外围利用,而且在这种利用下面,C语言没有竞争者。所以我感觉C语言会稳固在本人外围的利用中,并开始逐渐回升。 最初说点闲话,C++不会淘汰C语言。有了对象后你会发现再俭朴的对象也消耗资源,而且有了对象当前,总是情不自禁的去想继承这个事,一但继承实现了,你会发现继承带来的麻烦远超过你的设想。Java的发明人James被问到如果能够从新设计Java语言的话,第一个要做什么事?他说:“去掉对象”!作为一个已婚,有两个孩子的程序猿,我感同身受。如果大家感兴趣,我能够再写一个博客,聊聊C++和C的实在区别所在。 如果你看到这里,还什么都没记住。那就只记住一点:没人能预测将来。 如果再有人对你说C语言曾经过期了,最好本人思考一下,能求真最好,如果不能,至多要做到存疑。 02、为什么C仍占据统治位置?于一种计算机行业的技术来说尤其如此。自1972年诞生以来,C语言始终放弃龙腾虎跃的状态,时至今日它依然是咱们用来搭建软件世界的根底建筑材料之一。 但有时一种技术可能长期存在,只是因为人们还没有来得及创造新的货色来取代它而已。在过来的几十年里,呈现了许多其余语言——其中一些明确地被设计用于挑战C的主导地位,有些语言试图凭借本人的人气缓缓瓦解C语言的统治位置。 为C须要被替换掉的观点辩论是简略的。编程语言钻研和软件开发实际都暗示了如何比C更好地去做事。但历经数十年的钻研和开发,C语言的位置却仍旧巩固。很少有其余语言可能在性能、裸机兼容性或通用性等方面击败它。不过,2018年C是如何与那些明星编程语言竞争的呢,其中细节仍值得一看。 C vs. C ++当然了,C最常被拿来与C ++进行比拟,正如其名称自身所暗示的那样,C++作为对C语言的扩大而被创立进去。C ++和C之间的差别能够概括为C++更加宽泛(褒)或更加宽泛(贬),具体取决于这个问题你是问的C还是C++程序员。(笑) ...

November 17, 2021 · 1 min · jiezi

关于c:C-语言基础来喽

大家好,我是程序员cxuan!明天和大家一起学习C 语言根底! 前言C 语言是一门形象的、面向过程的语言,C 语言广泛应用于底层开发,C 语言在计算机体系中占据着不可代替的作用,能够说 C 语言是编程的根底,也就是说,不论你学习任何语言,都应该把 C 语言放在首先要学的地位上。上面这张图更好的阐明 C 语言的重要性 <img src="https://s1.ax1x.com/2020/09/10/wG83gx.png" alt="01" border="0" style="zoom:50%;" > 能够看到,C 语言是一种底层语言,是一种零碎层级的语言,操作系统就是应用 C 语言来编写的,比方 Windows、Linux、UNIX 。如果说其余语言是光鲜亮丽的表面,那么 C 语言就是灵魂,永远那么朴实无华。 原文链接:C 语言根底,来喽! C 语言个性那么,既然 C 语言这么重要,它有什么值得咱们去学的中央呢?咱们不应该只因为它重要而去学,咱们更在意的是学完咱们能学会什么,能让咱们取得什么。 C 语言的设计C 语言是 1972 年,由贝尔实验室的丹尼斯·里奇(Dennis Ritch)和肯·汤普逊(Ken Thompson)在开发 UNIX 操作系统时设计了C语言。C 语言是一门风行的语言,它把计算机科学实践和工程实际实践完满的交融在一起,使用户可能实现模块化的编程和设计。 计算机科学实践:简称 CS、是系统性钻研信息与计算的实践根底以及它们在计算机系统中如何实现与利用的实用技术的学科。C 语言具备高效性C 语言是一门高效性语言,它被设计用来充分发挥计算机的劣势,因而 C 语言程序运行速度很快,C 语言可能正当了应用内存来取得最大的运行速度 C 语言具备可移植性C 语言是一门具备可移植性的语言,这就意味着,对于在一台计算机上编写的 C 语言程序能够在另一台计算机上轻松地运行,从而极大的缩小了程序移植的工作量。 C 语言特点C 语言是一门简洁的语言,因为 C 语言设计更加凑近底层,因而不须要泛滥 Java 、C# 等高级语言才有的个性,程序的编写要求不是很严格。C 语言具备结构化管制语句,C 语言是一门结构化的语言,它提供的管制语句具备结构化特色,如 for 循环、if⋯ else 判断语句和 switch 语句等。C 语言具备丰盛的数据类型,不仅蕴含有传统的字符型、整型、浮点型、数组类型等数据类型,还具备其余编程语言所不具备的数据类型,比方指针。C 语言可能间接对内存地址进行读写,因而能够实现汇编语言的次要性能,并可间接操作硬件。C 语言速度快,生成的指标代码执行效率高。上面让咱们通过一个简略的示例来阐明一下 C 语言 ...

November 12, 2021 · 8 min · jiezi

关于c:自动化集成测试之解放程序员的利器真香

✨程序猿思维:能用工具解决的事绝不能入手!!!1.什么是CI/CD?CI (Continuous Integration):继续集成继续集成是指程序开发者将代码块推送到Git近程仓库时,每次Push或Merge都将触发并运行一系列脚本来构建、测试和验证提交的代码,验证通过后合并到仓库分支中。 CD (Continuous Deployment) :继续部署继续部署是继续集成的下一步动作,即通过CI形式胜利将代码合入指定仓库后,再将应用程序部署到生产环境的一系列动作。 CI/CD形式能够在开发阶段更及时的发现问题,升高代码审核人员的工作量,并进步代码品质,从而确保部署到生产环境的所有代码都合乎为应用程序建设的代码规范。CI/CD最大的劣势就在于主动执行脚本,从开发到部署简直不须要人为干涉。 CI/CD在国外大型开源我的项目中使用广泛,多人开发、单人开发、非开源我的项目一样能够很好的使用CI/CD能力。此外,CI/CD还能够灵便搭建,播种意想不到的便利性,帮忙程序员从反复而繁冗的工作中解放出来,更何况程序猿总喜爱说 2. CI/CD原理与流程CI/CD 继续集成的工具有Circle CI、Travis CI、Jenkins、Gitee Go、GitLab CI/CD等。当CI/CD与代码托管工具齐全集成时会带来微小的便利性,如GitLab CI/CD、Gitee Go,能够将代码的提交、审查与主动合入联合在一起,借助工具来把控开发代码的品质,并且排除人为干涉的误差性。 CI/CD的原理: 各大CI/CD工具的工作原理根本大同小异,以GitLab CI/CD为例。 GitLab CI/CD是怎么工作起来的呢?总结起来就两点: 将.gitlab-ci.yml文件增加到近程仓库的根目录;为GitLab我的项目仓库配置一个Runner。 说人话,.gitlab-ci.yml能够了解为流水线文件,应用 YAML语法形容,.gitlab-ci.yml文件形容了你要做什么事件,在此文件中指定构建、测试和部署的脚本。把.gitlab-ci.yml放到远端分支的根目录,你每次push或Merge代码到Git近程仓库时,Runner都会主动触发CI pipeline,去执行.gitlab-ci.yml流水线文件中形容的事。 Runner很好了解,就是一个用来跑仓库代码的构建、测试和部署的机器,能够是本地PC,也能够是一台服务器。Runner怎么配置、装置、注册,依据GitLab的阐明循序渐进就能够啦。 CI/CD的流程: 一旦你将提交推送到近程仓库的分支上,那么你为该我的项目设置的CI/CD管道将会被触发。GitLab CI/CD 是这样做: 运行自动化脚本(串行或并行) 代码Review并取得批准 构建并测试你的利用就像在你本机中看到的那样,应用Review Apps预览每个合并申请的更改 代码Review并取得批准合并feature分支到默认分支,同时主动将此次更改部署到生产环境如果呈现问题,能够轻松回滚通过GitLab UI所有的步骤都是可视化的 3.CI/CD集成计划抉择什么CI零碎? 这取决于你的需要以及打算应用它的形式。 CircleCI倡议用于小型我的项目,其次要指标是尽快开始集成。 当你从事开源我的项目时,倡议应用Travis CI,这些我的项目应在不同环境中进行测试。 Jenkins被举荐用于大型项目,在这些我的项目中,你须要进行大量自定义,这些自定义能够通过应用各种插件来实现, 你能够在这里更改简直所有内容,但此过程可能须要一段时间。 Gitee Go是Gitee外部集成的CI/CD工具,目前反对 Maven、Gradle、npm、Python、Ant、PHP、Golang等工具和语言的继续构建与集成能力。Gitee Go是属于Gitee的增值服务,须要你破费一笔小的费用。 GitLab CI/CD是GitLab外部集成的CI/CD工具,收费且高度集成是其最大特色。 这里列出了局部集成计划: VS Code + GitLab + GitLab CI/CD + ECS: VS Code + Gitee + Jenkins + ECS: ...

November 9, 2021 · 1 min · jiezi

关于c:C是如何调用C接口的

✨有的时候,当我想在c代码中调用c++接口,而后就编译报错了!!!引出问题C++反对函数重载的, 函数名雷同然而参数不同的重载函数在编译后链接的名字并不相同而能够被辨认, 这种状况下, 咱们引入一个中间层的办法同样能够实现C中调用C++的函数接口。 其实这与C中调用C++非重载根本函数成员的实现没有什么区别, 只是为各个重载函数均实现一套接口而已。 通常的做法//test.cpp#include <iostream>#include "hello.h"int getNum() { std::cout << "get number" << std::endl; return 123456;}这时,咱们须要对该c++函数,进行申明,通知编译器,须要按c的命名规定来: //test.h#ifdef __cplusplusextern "C" {#endifint getNum();#ifdef __cplusplus}#endif#endif这时,咱们就能够在C源码中调用getNum接口了。 重载函数如果你想在 C 里调用重载函数,则必须提供不同名字的包装,这样能力被 C 代码调用。首先是咱们的C++接口, 如下所示: // add.cpp//#include <iostream>int add(const int a, const int b){ return (a + b);}double add(const double a, const double b){ //std::cout <<a <<", " <<b <<std::endl; return (a + b);}咱们为此实现一个中间层libadd.cpp, 通过C++编译器用extern "C"将其编译成C编译器可辨认的接口: // libadd.cppint add(const int a, const int b);double add(const double a, const double b);#ifdef __cplusplusextern "C"{#endifint call_cpp_add_int(const int a, const int b){ return add(a, b);}double call_cpp_add_double(const double a, const double b){ return add(a, b);}#ifdef __cplusplus}#endif最初是咱们的C源程序, 调用咱们的中间层: ...

November 8, 2021 · 1 min · jiezi

关于c:如何编译多个c文件

编译多文件咱们有以下三个文件file1.c #include "stdio.h"#include "file2.h"int main(void){ printf("%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__); foo(); return 0;}file2.h void foo(void);file2.c #include <stdio.h>#include "file2.h"void foo(void) { printf("%s:%s:%d \n", __FILE__, __FUNCTION__, __LINE__); return;}执行 gcc file1.c file2.c -o server 生成可执行程序server, 执行./server 咱们能够失去以下输入 file1.c:main:5file2.c:foo:5这样就能够编译多文件的程序了。linux下还须要make程序来自动化编译等操作。增加Makefile文件 server : file1.o file2.o $(CC) -o $@ $^.PHONY: cleanclean: rm *.o server执行make, 就能编译程序了。执行make clean 就会删除make产生的临时文件。Makefile有以下模式 target: require action其中target时产物,require时生成target的依赖。 action是动作,能够是编译程序的动作,也可能是输入些信息。下面的例子中target是server, 依赖是file1.o, file2.o。 make会主动.o 文件执行 cc -c .c -o *.o 命令。下面例子中执行cc -c file1.c -o file1.o 和 cc -c file2 -o file2.o。$(CC) 是内置变量,linux下会解释成cc。$@是target, $^是require。这样就能生成可执行程序server了。上面加了个clean, 因为不是真正的文件,须要用.PHONY: clean 阐明是伪文件。 ...

November 4, 2021 · 1 min · jiezi

关于c:编程艺术剖析-darknet-parsenetworkcfg-接口

 欢送关注我的公众号 [极智视界],回复001获取Google编程标准 O_o >_<  o_O O_o ~_~ o_O 本文剖析和介绍一下 darknet parse_network_cfg 接口,这个接口比拟硬核,次要做模型构造的加载与算子的实现。 1、darknet 数据加载例程   之前的文章《【编程艺术】分析 darknet read_data_cfg 接口》曾经介绍了一下 darknet 指标检测的数据加载流程,并介绍了.data 和 .names 的加载实现。   接下来这里 parse_network_cfg 接口次要做 .cfg 模型构造的加载,外面波及的货色略微多一些。 2、parse_network_cfg 接口   来看一下 parse_network_cfg 的实现: network parse_network_cfg(char *filename){ return parse_network_cfg_custom(filename, 0, 0);}   能够看到外面调用了 parse_network_cfg_custom 函数,这是次要的性能实现函数,也是这里重点要分析的。这个函数的实现有 451 行,这里就不间接贴了,筛选一些比拟要害的中央拿出来说一下。 首先是读 cfg: list *sections = read_cfg(filename);   读 cfg 采纳 read_cfg 接口,先须要说一下 darknet 里用链表存网络结构的数据结构:整个网络采纳链表进行存储,链表的值域为 section 块,section 块寄存 [net]、[convolution]、[yolo]... 这些构造,来看一下 section 的定义就很清晰了,其中 type 就是记录块的类别,即 [net] 或 [convolution] 或 [yolo] 等字符串。 ...

November 3, 2021 · 3 min · jiezi

关于c:15213-动态内存分配

15-213 / 14-513 / 15-513, Fall 2021Malloc Lab: Writing a Dynamic Storage AllocatorAssigned: October 12, 2021This lab requires submitting two versions of your code: one as an initial checkpoint, and the second asyour final version. The due dates of each part are indicated in the following table:Version Due Date Max. Grace Days Last Hand-in Date Weight in Final GradeCheckpoint Oct. 26 2 Oct. 28 4%Final Nov. 2 2 Nov. 4 7%Don’t forget that due dates are at 11:59pm Eastern Time (presently UTC-4). See section 7 for details on howeach section is scored.1 IntroductionIn this lab you will write a dynamic memory allocator which will consist of the malloc, free, realloc, andcalloc functions. Your goal is to implement an allocator that is correct, efficient, and fast.We strongly encourage you to start early. The total time you spend designing and debugging can easilyeclipse the time you spend coding.Bugs can be especially pernicious and difficult to track down in an allocator, and you will probably spenda significant amount of time debugging your code. Buggy code will not get any credit.This lab has been heavily revised from previous versions. Do not rely on advice or information you mayfind on the Web or from people who have done this lab before. It will most likely be misleading or outrightwrong.1 Be sure to read all of the documentation carefully and especially study the baseline implementationwe have provided.1Not to mention the fact that it would be an academic integrity violation!1Contents1 Introduction 12 Logistics 33 Required Functions 44 Support Routines 65 Programming Rules 76 Driver Programs 96.1 Trace files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96.2 Command-line arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 Scoring 117.1 Autograded score . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117.1.1 Performance index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117.1.2 Utilization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117.1.3 Throughput . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127.1.4 Autograded deductions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127.2 Heap Consistency Checker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137.3 Style . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137.4 Handin Instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 Useful Tips 159 Office Hours 1610 Strategic Advice 17A Performance Evaluation 19A.1 Approximate Expected Results from Optimizations . . . . . . . . . . . . . . . . . . . . . . 19A.2 Machine Dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19A.3 Performance Points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19B Viewing Heap Contents with GDB 21B.1 Viewing the heap without a helper function . . . . . . . . . . . . . . . . . . . . . . . . . . 21B.2 Viewing the heap with the hprobe helper function . . . . . . . . . . . . . . . . . . . . . . 2222 LogisticsThis is an individual project. You should do this lab on one of the Shark machines.To get your lab materials, click “Download Handout” on Autolab, enter your Andrew ID, and follow theinstructions. Then, clone your repository on a Shark machine by running:$ git clone https://github.com/cmu15213f2...<YOUR USERNAME>.gitor, if you use SSH keys, All the code for your allocator must be in this file. The rest of theprovided code allows you to evaluate your allocator. Using the command make will generate four driverprograms: mdriver, mdriver-dbg, mdriver-emulate, and mdriver-uninit, as described in section 6.Your final autograded score is computed by driver.pl, as described in section 7.1.To test your code for the checkpoint submission, run mdriver and/or driver.pl with the -C flag. Totest your code for the final submission, run mdriver and/or driver.pl with no flags.These commands will report accurate utilization numbers for your allocator. They will only reportapproximate throughput numbers. The Autolab servers will generate different throughput numbers, andthe servers’ numbers will determine your actual score. This is discussed in more detail in Section 7.33 Required FunctionsYour allocator must implement the following functions. They are declared for you in mm.h and you will findstarter definitions in mm.c. Note that you cannot alter mm.h in this lab.bool mm_init(void);void *malloc(size_t size);void free(void *ptr);void realloc(void ptr, size_t size);void *calloc(size_t nmemb, size_t size);bool mm_checkheap(int);We provide you two versions of memory allocators:mm.c: A fully-functional implicit-list allocator. We recommend that you use this code as your starting point.Note that the provided code does not implement block coalescing. The absence of this feature will causeexternal fragmentation to be very high, so you should implement coalescing. We strongly recommendconsidering all cases you need to implement before writing code for coalesce_block; the lectureslides should help you identify and reason about these cases.mm-naive.c: A functional implementation that runs quickly but gets very poor utilization, because it neverreuses any blocks of memory.Your allocator must run correctly on a 64-bit machine. It must support a full 64-bit address space, eventhough current implementations of x86-64 machines support only a 48-bit address space.Your submitted mm.c must implement the following functions:bool mm_init(void): Performs any necessary initializations, such as allocating the initial heap area. Thereturn value should be false if there was a problem in performing the initialization, true otherwise.You must reinitialize all of your data structures each time this function is called, because thedrivers call your mm_init function every time they begin a new trace to reset to an empty heap.void *malloc(size_t size): Returns a pointer to an allocated block payload of at least size bytes. Theentire allocated block should lie within the heap region and should not overlap with any other allocatedblock.Your malloc implementation must always return 16-byte aligned pointers, even if size is smaller than16.void free(void *ptr) : If ptr is NULL, does nothing. Otherwise, ptr must point to the beginning of ablock payload returned by a previous call to malloc, calloc, or realloc and not already freed. Thisblock is deallocated. Returns nothing.void realloc(void ptr, size_t size): Changes the size of a previously allocated block.If size is nonzero and ptr is not NULL, allocates a new block with at least size bytes of payload,copies as much data from ptr into the new block as will fit (that is, copies the smaller of size, or thepayload size of ptr, bytes), frees ptr, and returns the new block.If size is nonzero but ptr is NULL, does the same thing as malloc(size).If size is zero, does the same thing as free(ptr) and then returns NULL.Your realloc implementation will have only minimal impact on measured throughput or utilization. Acorrect, simple implementation will suffice.4void *calloc(size_t nmemb, size_t size): Allocates memory for an array of nmemb elements ofsize bytes each, initializes the memory to all bytes zero, and returns a pointer to the allocated memory.Your calloc implementation will have only minimal impact on measured throughput or utilization. Acorrect, simple implementation will suffice.bool mm_checkheap(int line): Scans the entire heap and checks it for errors. This function is calledthe heap consistency checker, or simply heap checker.A quality heap checker is essential for debugging your malloc implementation. Many malloc bugsare too subtle to debug using conventional gdb techniques. A heap consistency checker can help youisolate the specific operation that causes your heap to become inconsistent.Because of the importance of the consistency checker, it will be graded, by hand; section 7.2 describesthe requirements for your implementation in greater detail. We may also require you to write your heapchecker before coming to office hours.The mm_checkheap function takes a single integer argument that you can use any way you want. Onetechnique is to use this argument to pass in the line number where it was called, using the LINEmacro:mm_checkheap(__LINE__);This allows you to print the line number where mm_checkheap was called, if you detect a problem withthe heap.The driver will sometimes call mm_checkheap; when it does this it will always pass an argument of 0.The semantics of malloc, realloc, calloc, and free match the semantics of the functions with thesame names in the C library. You can type man malloc in the shell for more documentation.54 Support RoutinesTo satisfy allocation requests, dynamic memory allocators must themselves request memory from the operatingsystem, using “primitive” system operations that are less flexible than malloc and free. In this lab, youwill use a simulated version of one such primitive. It is implemented for you in memlib.c and declared inmemlib.h.void *mem_sbrk(intptr_t incr): Expands the heap by incr bytes, and returns a generic pointer to thefirst byte of the newly allocated heap area. If the heap cannot be made any larger, returns (void *)-1. (Caution: this is different from returning NULL.)Each time your mm_init function is called, the heap has just been reset to zero bytes long.mem_sbrk cannot make the heap smaller; it will fail (returning (void *) -1) if size is negative.(Data type intptr_t is defined to be a signed integer large enough to hold a pointer. On our machinesit is the same size as size_t, but signed.)This function is based on the Unix system call sbrk, but we have simplified it by removing the abilityto make the heap smaller.You can also use these helper functions, declared in memlib.h:void *mem_heap_lo(void): Returns a generic pointer to the first valid byte in the heap.void *mem_heap_hi(void): Returns a generic pointer to the last valid byte in the heap.Caution: The definition of “last valid byte” may not be intuitive! If your heap is 8 bytes large, then thelast valid byte will be 7 bytes from the start—not an aligned address.size_t mem_heapsize(void): Returns the current size of the heap in bytes.You can also use the following standard C library functions, but only these: memcpy, memset, printf,fprintf, and sprintf.Your mm.c code may only call the externally-defined functions that are listed in this section. Otherwise, itmust be completely self-contained.65 Programming Rules• Any allocator that attempts to detect which trace is running will receive a penalty of 20 points. Onthe other hand, you should feel free to write an adaptive allocator—one that dynamically tunes itselfaccording to the general characteristics of the different traces.• You may not change any of the interfaces in mm.h, or any of the other C source files and headers besidesmm.c. (Autolab only processes your mm.c; it will not see changes you make to any other file.) However,we strongly encourage you to use static helper functions in mm.c to break up your code into small,easy-to-understand segments.• You may not change the Makefile (again, Autolab will not see any changes you make there) and yourcode must compile with no warnings using the warnings flags we selected.• You are not allowed to declare large global data structures such as large arrays, trees, or lists in mm.c.You are allowed to declare small global arrays, structs, and scalar variables, and you may have as muchconstant data (defined with the const qualifier) as you like. Specifically, you may declare no morethan 128 bytes of writable global variables, total. This is checked automatically, as described inSection 7.1.4.The reason for this restriction is that global variables are not accounted for when calculating yourmemory utilization. If you need a large data structure for some reason, you should allocate space for itwithin the heap, where it will count toward external fragmentation.• Dynamic memory allocators cannot avoid doing operations that the C standard labels as “undefinedbehavior.” They need to treat the heap as a single huge array of bytes and reinterpret those bytes asdifferent data types at different times. It is rarely appropriate to write code in this style, but in thislab it is necessary.We ask you to minimize the amount of undefined behavior in your code. For example, instead ofdirectly casting between pointer types, you should explicitly alias memory through the use of unions.Additionally, you should confine the pointer arithmetic to a few short helper functions, as we have triedto do in the handout code.• In the provided baseline code, we use a zero-length array to declare a payload element in the blockstruct. This is a non-standard compiler extension, which, in general, we discourage the use of, but inthis lab we feel it is better than any available alternative.A zero-length array is not the same as a C99 “flexible array member;” it can be used in places where aflexible array member cannot. For example, a zero-length array can be a member of a union. Usingzero-length arrays this way is our recommended strategy for declaring a block struct that might containpayload data, or might contain something else (such as free list pointers).• The practice of using macros instead of function definitions is now obsolete. Modern compilers canperform inline substitution of small functions, eliminating the overhead of function calls. Use of inlinefunctions provides better type checking and debugging support.In this lab, you may only use #define to define constants (macros with no parameters) and debuggingmacros that are enabled or disabled at compile time. Debugging macros must have names that beginwith the prefix “dbg_” and they must have no effect when the macro-constant DEBUG is not defined.Here are some examples of allowed and disallowed macro definitions:7 ...

October 31, 2021 · 35 min · jiezi

关于c:C进阶19编译过程简介

Summary1)编译器个别由以下4局部组成:预处理器、编译器、汇编器、链接器 2)点击Build之后,IDE会进行预编译(生成两头.i文件)、编译(生成汇编代码.s文件)、汇编(生成指标文件.o文件)、链接(生成可执行程序.out文件)。 3)预编译会做的事件:解决正文(应用空格代替);开展宏(删除'#define');解决#结尾的符号(包含解决条件编译指令、开展头文件、#pragma指令等) 4)编译器所做工作 对预处理.i文件进行词法剖析、语法分析、语义剖析 词法剖析:剖析关键字、标识符、立刻数等是否非法语法分析:剖析表达式是否恪守语法规定语义剖析:在语法分析的根底上进一步剖析表达式是否非法剖析完结后进行代码优化生成相应的汇编代码文件5)汇编器所做工作 将汇编代码转变为机器的可执行指令每条汇编语句简直都对应一条机器指令编译过程简介1、预编译预编译做的是文本处理工作: 正文用空格代替开展所有的宏定义,并将#define删除解决条件编译指令#if, #ifdef, #elif, #else, #endif解决#include,开展被蕴含的头文件保留编译器须要应用的#pragma指令预处理指令示例:gcc - E test.c -o test.i 2、编译编译器所做工作 对预处理.i文件进行词法剖析、语法分析、语义剖析 词法剖析:剖析关键字、标识符、立刻数等是否非法语法分析:剖析表达式是否恪守语法规定语义剖析:在语法分析的根底上进一步剖析表达式是否非法剖析完结后进行代码优化生成相应的汇编代码文件编译指令示例:gcc -S test.i -o test.s 3、汇编汇编器所做工作 将汇编代码转变为机器的可执行指令每条汇编语句简直都对应一条机器指令汇编指令示例:gcc -c test.s -o test.o(.o文件被称为指标文件,并不是最终的可执行程序;个别一个.c文件就对应到一个.o指标文件) 本文总结自“狄泰软件学院”唐佐林老师《C语言进阶课程》。如有错漏之处,恳请斧正。

October 30, 2021 · 1 min · jiezi

关于c:C进阶18三目运算符和逗号表达式

Summary1)在C语言中,三目运算符返回的后果是一个右值,并不是一个变量(不能放在赋值符号左侧) 2)三目运算符的返回类型: 通过隐式类型转换规定返回b和c中的较高类型(留神:char和short在运算时会隐式转换成int)当b和c不能隐式转换到同一类型时编译出错3)逗号表达式(exp1, exp2, ... expN) 逗号表达式用于将多个子表达式连贯为一个表达式逗号表达式的值为最初一个子表达式的值(前N-1个子表达式能够没有返回值)计算程序为从左到右4)个别一行代码实现某种性能时,往往须要用到递归 + 逗号表达式 + 三目运算符 三目运算符和逗号表达式1、三目运算符三目运算符(expression ? a : b):当expression的值为真时,返回a的值;否则返回b的值。 代码浏览 int a = 1;int b = 2;int c = 0;c = a < b ? a : b; // c = 1 (a < b ? a : b) = 3; // error, lvalue required as left operand of assignment三目运算符(expression ? a : b)的返回类型: 通过隐式类型转换规定返回b和c中的较高类型当b和c不能隐式转换到同一类型时编译出错 char c = 0;short s = 0;int i = 0;double d = 0;char* p = "str";printf("%d\n", sizeof(c ? c : s)); // 4, 返回类型隐式转换为intprintf("%d\n", sizeof(i ? i : d)); // 8,返回类型隐式转换为doubleprintf("%d\n", sizeof(d ? d : p)); // error,double和char*不能隐式类型转换为同一类型2、逗号表达式逗号表达式(exp1, exp2, ... expN) ...

October 29, 2021 · 2 min · jiezi

关于c:新手必须要注意的编程范式

编程语言与成百种编程语言(Programming Language)相比,编程范式(Programming Paradigm、范式)要少得多。如图所示,共有 27 种范式。少数范式之间仅相差一个或几个概念。 次要的范式最罕用的范式有三个:过程试编程,面向对象编程(OOP),函数式编程(FP)。而后咱们介绍一下新兴的第四种范式也就是面向切面编程(AOP)。 过程试编程过程式编程(Procedural programming)的外围在于模块化,在实现过程中应用了状态,依赖了内部变量,导致很容易影响左近的代码,可读性较低,前期的保护老本也较高。 过程试编程经验了倒退的两个阶段,非结构化到结构化: 非机构化编程(Unstructured programming):机器语言和汇编语言的编程范式被认为是非结构化编程,没有封装函数的概念,代码中 goto 语句满天飞的状态。 结构化编程(Structured programming):形象了机器的行为,屏蔽了局部计算机的硬件细节。代表语言就是咱们罕用的 C 语言。 有时结构化编程,也称作过程式编程,或面向过程编程。 def get_shannon_info(output): """获取shannon类型flash卡信息"""def check_health(): time_left = float(sub_info["life_left"]) if time_left < DISK_ALARM_LIFETIME: message = "time left is less than {}%".format(DISK_ALARM_LIFETIME) return message temperature = float(sub_info["temperature"].split()[0]) if temperature > DISK_ALARM_TEMPERATURE: message = "temperature is over than {} C".format(DISK_ALARM_TEMPERATURE) return message return "healthy"http://tags.astro.sina.com.cn... result = {}all_info = _get_shannon_info(output)for info in all_info: sub_info = {} sub_info["available_capacity"] = info.get("disk_capacity", "") sub_info["device_name"] = info.get("block_device_node", "") sub_info["firmware_version"] = info.get("firmware_version", "") sub_info["interface"] = "PCIe" sub_info["life_left"] = str(info.get("estimated_life_left", "").replace("%", "")) sub_info["pcie_id"] = info.get("pci_deviceid", "") sub_info["pcie_length"] = "" sub_info["pcie_type"] = "" sub_info["physical_read"] = info.get("host_read_data", "") sub_info["physical_write"] = info.get("total_write_data", "") sub_info["serial_number"] = info.get("serial_number") sub_info["temperature"] = info.get("controller_temperature") sub_info["type"] = info["type"] sub_info["error_msg"] = check_health() sub_info["status"] = "ok" if sub_info["error_msg"] == "healthy" else "error" if sub_info["serial_number"]: result[sub_info["serial_number"]] = sub_info else: result[sub_info["device_name"]] = sub_inforeturn result面向对象编程面向对象编程(Object-oriented programming)的外围在于形象,提供清晰的对象边界。联合封装、集成、多态个性,升高了代码的耦合度,晋升了零碎的可维护性。C++ 和 之后的 Java 成为支流。 ...

October 29, 2021 · 3 min · jiezi

关于c:C进阶17和操作符分析

Summary1)++和--参加混合运算后果是不确定的,如r = (i++) + (i++);等 C++只规定了++和--对应指令的绝对执行秩序(取值和自增的绝对程序)++和--对应的汇编指令不肯定间断执行在混合运算中,++和--的汇编指令可能被打断执行 (取值和自增可能被打断了,两头插入了其余代码)2)编译器的贪婪法 编译器以从左向右的程序,一个一个地尽可能多的读入字符当读入的字符不可能和曾经读入的字符组成非法符号为止3)空格能够作为C语言中一个残缺符号的休止符,编译器读入空格后会立刻对之前读入的符号进行解决。 ++和--操作符分析1、Demo1以下代码的输入是? int i = 0;int r = 0;r = (i++) + (i++) + (i++);printf("i = %d\n, r = %d\n", i, r);r = (++i) + (++i) + (++i);printf("i = %d\n, r = %d\n", i, r);代码初步剖析: 第一行输入:i = 3, r = 3; // 依照从左向右的计算方法,i先取值,再自增, // 则r = 0 + 1 + 2 = 3;第二行输入:i = 6, r = 16; // 同上,r = 4 + 5 + 6 = 15;以上代码在VS2015编译器的理论输入后果为: ...

October 25, 2021 · 2 min · jiezi

关于c:C语言-浮点型存储

浮点型存储形式依照IEEE 754 规定贮存浮点型数据 #include <stdio.h>int main(){ int n = 9; //原码反码补码 //00000000000000000000000000001010 float* pFloat = (float*)&n; printf("n=%d\n",n); printf("*pFloat=%f\n",*pFloat); //以浮点数的视角看内存中贮存的二进制数据 //0(S负数) 00000000 (E 0+127) 000000000001010 (M) *pFloat = 9.0; //以浮点数的形式贮存二进制数据 //1001.0 1.001*2^3 E=3 //0 10000010 001000000000000000 printf("num=%d\n",n); //以整型形式读取 printf("*pFloat=%f\n",*pFloat); //浮点数形式读取 return 0;}更多建站及源码交易信息请见 GoodMai好买网

October 25, 2021 · 1 min · jiezi

关于c:CPT109-C难点解析

CPT109 C Programming and Software Engineering 1 – ASSESSMENT 1Assessment Number 1Contribution to Overall Marks 15%Issue Date Monday, 11th October 2021 (Week 5)Submission Deadline Monday, 25th October 2021, 00:01 (Week 7)Assessment OverviewThis assessment aims at testing some basic concepts of C programming and initiates theroutine of code development using the software development process (SDP). There are 3exercises, for exercise 1 and 2 only your code needs to be submitted. For exercise 3 you mustsubmit code and your SDP report. The SDP was presented in Lecture 1 you should only focuson the first five steps: ...

October 22, 2021 · 3 min · jiezi

关于c:32547-unix编程

32547 Faculty of Engineering and Information TechnologySubject 32547 UNIX Systems Programming, Spring 2021AssignmentDescriptionThis assignment is an individual programming assignment using Python. It addresses objectives 2and 3 as listed in the Subject Outline document.No limits apply to the number of lines of code of the program.Assignments are to be completed individually (this might be checked with the use of anti‐plagiarism tools such as Turnitin). You should not receive help in the preparation of thisassignment, nor ask anyone else to prepare it on your behalf in any way.  MarksThe assignment corresponds to 30% of the total marks.SubmissionThe completed assignment is due by 5:00pm of Friday 29 October 2021.  PLEASE PAY ATTENTION TO THE FOLLOWING SUBMISSION INSTRUCTIONS: ...

October 22, 2021 · 6 min · jiezi

关于c:从c到c

mapinsert和emplace区别,插入构造体时,emplace比insert少一次拷贝结构,举荐应用emplace结构的两种办法 map[1] = 2map.insert(std::pair<int, int>(2, 4));map.emplace(2,4)操作符重载 mymap[1] = 2;mymap[2] = 3;mymap[1] = 4;//mymap.size() == 2然而输入mymap[10]的值等于0, 同时size变成了3, 起因:会调配一个默认值为0给新的key, 这个val到底是否无效, 所以记得用find的办法,保障是无效的键值对map之间的赋值, 会耗费十分对的资源, map2 = map1,耗时931个时钟, map提供了swap办法, 不是内存拷贝,malloc这样的操作,只是把两者指针做替换,只耗费1个时钟,后续参考右值。multiple_map,容许key雷同容许传入第三个参数, 仿函数 map<int, int, less<int> > mymap;

October 19, 2021 · 1 min · jiezi

关于c:CSc-352-链接表实现

CSc 352 (Spring 2019): Assignment 11Due Date: 11:59PM Wed, May 1The purpose of this assignment is to work with linked lists, memory allocation, command linearguments, reading from a file, using free(), representing graphs, and doing more complicatedmanipulation of pointers.General Requirements Your C code should adhere to the coding standards for this class as listed in theDocuments section on the Resources tab for Piazza. This includes protecting againstbuffer overflows whenever you read strings.Your programs should indicate if they executed without any problems via their exitstatus, i.e., the value returned by the program when it terminates:Execution Exit StatusNormal, no problems 0Error or problem encountered 1Under bash you can check the exit status of a command or program cmd by typing thecommand "echo $?" immediately after the execution of cmd. A program can exit withstatus n by executing "exit(n)" anywhere in the program, or by having main() executethe statement "return(n)".Remember your code will be graded on lectura using a grading script. You should testyour code on lectura using the diff command to compare your output to that of theexample executable.Your code must show no errors when run with valgind.You must free all your allocated memory before your program exits.TestingExample executables of the programs will be made available. You should copy and run theseprograms on lectura to test your program’s output and to answer questions you might have abouthow the program is supposed to operate. Our class has a home directory on lectura which is:/home/cs352/spring19You all have access to this directory. The example programs will always be in the appropriateassignments/assg#/prob# subdirectory of this directory. They will have the same name as theassigned program with “ex” added to the start and the capitalization changed to maintaincamelback. So, for example, if the assigned program is theBigProgram, then the exampleexecutable will be named exTheBigProgram. You should use the appropriate UNIXcommands to copy these executables to your own directory.Your programs will be graded by a script. This will include a timeout for all test cases. Theremust be a timeout or programs that don’t terminate will cause the grading script to never finish.This time out will never be less than 10 times the time it takes the example executable tocomplete with that test input and will usually be much longer than that. If your program takes anexceedingly long time to complete compared to the example code, you may want to think abouthow to clean up your implementation.MakefilesYou will be required to include a Makefile with each program. Running the command:make progNameshould create the executable file progName, where progName is the program name listed for theproblem. The gcc commands in your Makefile that create the object files must include the -Wallflag. Other than that, the command may have any flags you desire.Submission InstructionsYour solutions are to be turned in on the host lectura.cs.arizona.edu. Since the assignment willbe graded by a script, it is important you have the directory structure and the names of the filesexact. Remember that UNIX is case sensitive, so make sure the capitalization is also correct. Forall our assignments the directory structure should be as follows: The root directory will be namedassg#, where # is the number of the current assignment. Inside that directory should be asubdirectory for each problem. These directories will be named prob# where # is the number ofthe problem within the assignment. Inside these directories should be any files required by theproblem descriptions.To submit your solutions, go to the directory containing your assg11 directory and use thefollowing command:turnin cs352s19-assg11 assg11Problemsprob1: baconWrite a program called bacon which calculates the Bacon score(https://en.wikipedia.org/wiki... ) of various actors based on theinformation given in an input file. Kevin Bacon is a movie actor and the Bacon score for anymovie actor is the number of movies it takes to connect Kevin Bacon with that actor. Thedefinition is as follows: Kevin Bacon has a Bacon score of 0 Any actor who was in a movie with Kevin Bacon has a Bacon score of 1 For any actor X, if the lowest possible Bacon score of any actor X has been in a moviewith is N, the X's Bacon score is N + 1It may be hard to follow the outline above, but the concept is not that deep. Read through thewiki page linked to above if you are confused.Basically, this is a graph problem. The actors are the vertices. The edges connecting the actorsare movies. There is an edge between the vertices representing actors A and B if and only if Aand B appeared in a movie together. An actor's Bacon score is then the smallest number of edgesconnecting the actor to Kevin Bacon. Invocation: Your program will be invoked with a required argument giving the file nameof a text file containing movie names and cast lists and an optional flag to tell theprogram whether to print out just the Bacon score or to print out the score together withthe path that generated it. The invocation will look like:bacon [-l] inFilewhere inFile is the name of a file which contains the movie list from which you willbuild your graph and –l (that's a lowercase L) is an optional flag. To make our program"UNIX like" we will allow the arguments to appear in any order and the option flag maybe specified multiple times. Here are some examples of legal invocations:bacon myFile –lbacon –l –l myFilebacon myFileThe following would be illegal invocations:bacon –l //has no file specifiedbacon fileName fileName //too many argumentsbacon –ll myFile //not a legal optionIf the invocation is illegal, you should print an error message to stderr indicating how theprogram is used, and exit with a status of 1. If you are confused about what is legal andwhat is not, experiment with the example executable. Movie File: The movie file whose name is given as a command line argument willcontain a list of movies and their cast lists. The format of the file is as follows:Move: <name of movie><actor 1><actor 2><actor n>Movie: <name of movie><actor 1> . . .where the actors listed (one per line) after the movie name are the actors in that movie.An example input file is in the subdirectory for this project of the class home directory onlectura. The file may contain blank lines (lines containing only white space) and theseshould be ignored. A single space will follow the keyword "Movie:". The name of themovie is considered to be the string starting at the character beyond that space andcontinuing until the end of the line but NOT including the '\n'. The actor's name iseverything on the line except for the possible newline ('\n') at the end. To simplify theprogram, do not worry about trimming white space from the ends of the lines (other thanthe '\n') or capitalization. In other words the actor's "John Wayne", "John Wayne ", "johnwayne", and " John Wayne" can all be considered to be different by your program. Behavior: After reading the file of cast lists and creating your graph, your program willdo the following:read in a line from stdin containing an actor's namecompute the Bacon score for that actor (using a breadth first search)print the Bacon score (and the connecting actors and movies if –l option invoked)to stdout according to the format specified below.until no further input can be read. ? Assumptions: You can assume the following:o The movie file, if it exists, is in correct format. In other words you may assumethe first nonblank line contains a movie name. You may also assume that if a linestarts with "Movie: ", then the line continues with some name. Note that sinceblank lines are legal, and empty file is in fact a legal movie file. Output: Output should be printed to stdout. To print out the score, use the formatprintf("Score: %d\n", score)where score is the calculated Bacon score. If there is no path between the actor and KevinBacon, your program should print "Score: No Bacon!" on a single line.If the actor queried is not in the graph, print a message to stderr and continue readingqueries. As always, whenever you print to stderr, when your program finally exits itshould exit with a status of 1.The –l optionIf the –l option is specified when the program is invoked, your program should print thelist of movies and actors connecting the queried actor to Kevin Bacon. The format for thisoutput should be<Queried Actor>was in <Movie Name> with<Actor>was in <Movie Name> with<Actor>. . .was in <Movie Name> withKevin BaconKeeping track of this list is more difficult and only 10% of the test cases will involve thisoption and they will be for extra credit. In other words you can still get 90/90 (100%) onthe assignment even if you fail to implement the –l option (you must still recognize aninvocation with the –l option as legal though), or 100/90 if you correctly implement the –loption. Also note that while the Bacon score is unique, the list printed out may not be.This means that if you are testing this option you may end up with a different output thanthe example executable and still be correct. Don't worry about getting the same list as theexample as long as your list is correct. When I test this part of the program I will use testcases that have only one path to generate the Bacon score. You may want to create suchtest cases yourself. (The example movie file should do.)? Data Structures:Once again you will use linked lists to represent the graph. The vertices of the graph willbe the actors. The edges will be the movies. If you are implementing the –l option theedges will need to contain the movie name.There are certainly variations on this. I used a linked list of actors. Each actor contains alinked list of movies (nodes which point to a movie). Each movie contains a linked list ofactors (nodes pointing to an actor). The Algorithm:A depth first search will not work here. A depth first search finds if there is a pathbetween two vertices. We want to find the shortest path between two vertices. Toaccomplish this, we will use a breadth first search. A depth first search recursivelysearches all the children of each vertex. A breadth first search puts all the children on aqueue. This way all the children are search before the grandchildren, etc. Here is thealgorithm for a breadth first search:BFS(Start, Target)mark Start as queuedset level of Start to 0add Start to the queuewhile queue is not empty do Take A from top of queue For all children C of A do if C == Target return level of A + 1 //found, score A.level + 1 if C not queued mark C as queued set level of C to level of A + 1 add C to queuereturn Target not found //If you get through loop without //finding Target, there is no//path from Start to TargetNote that in C you will have to implement this queue with a linked list. Don't forget tofree it again after you're done using it.Here's a hint for implementing the –l option. It requires you be able to trace the path fromStart to Target. If some actor A is put on the queue when looking at the children of someactor B, the path to A comes from B. If your structure for nodes of the queue contains alink to this "parent" node, then you can following these links from the queue node for theTarget back to the queue node for the Start. (i.e. It records your path.) Error Conditions:o Fatal errors: Bad invocation of program; input file cannot be opened for reading.o Non-fatal errors: Queried actor is not in the graph.

October 18, 2021 · 10 min · jiezi

关于c:COMP-321-编程指南

COMP 321April 24, 2019Questions on this exam may refer to the textbook as well as to the manual pages on CLEAR.Therefore, you should not start the exam until you are in a position to access both.As a reminder, the notation fdopen(3) means that the manual page for the function fdopencan be displayed with the command man 3 fdopen.You may review any section of the textbook and any manual page on CLEAR during the exam,and not just those explicitly referenced by the questions. Moreover, you may review any of thelecture notes, labs, and assignments that the instructors have provided to you or any notes thatyou have taken for this class. You may also use CLEAR to develop and test your C code for thisexam. You may not consult any other sources of information, including other textbooks, web sites,or people, aside from the instructors.This is a 5 hour exam. You must take the exam in one continuous block of time. You maytake one break of up to one hour during the exam. Your exam period begins as soon as you lookat any page of the exam other than these instructions. Indicate in your exam submission the dateand time at which you start the exam, the time at which you start your break, the time at whichyou end your break, and the time at which you end the exam.Once you begin the exam, you may not discuss the exam with anyone other than the instructorsuntil the end of the finals period. If you find anything in the exam to be ambiguous, clearly stateall of the assumptions that you are making in solving the problem.All of the questions have brief answers of either a single paragraph or a single C function thatis small in size. Always explain your answer and comment any C code you write to explain whatit does. Most of your score will be determined by your explanation. Turn in your answers throughCanvas by 5PM on Wednesday, May 1st. Submit your answers in the form of a text file (.txt),following the same formatting guidelines as for your programming assignments.1 of 8 ...

October 17, 2021 · 5 min · jiezi

关于c:C进阶16位运算符

Summary1)C语言中的位运算符: 运算符意义规定&按位与全1得1,有0得0I按位或有1得1,全0得0^按位异或雷同为0,不同得1~取反1变0, 0变1<<左移高位抛弃,低位补0·>>右移高位补符号位,低位舍弃2)左移、右移的留神点: 左操作数必须是整数类型 char和short被隐式转换为int后进行操作右操作数的范畴必须为:[0,31],否则后果未定义(不同编译器处理结果不同)左移运算符<<将运算数的二进制位左移,成果相当于乘以2的n次方,效率更高右移运算符>>将运算数的二进制位右移,成果相当于除以2的n次方,效率更高防止位运算符、逻辑运算符、数学运算符等混合运算,如果必须这样,应用括号示意好计算程序。(单算移比、按逻三赋)3)位运算留神点: 位运算没有短路规定,每个操作数都会参加运算位运算的后果是整数,而不是0或1位运算的优先级高于逻辑运算(单算移比 按逻三赋)4)替换两个整形变量的值: Demo1:局部和形式:不应用两头变量,但存在溢出的问题 #define SWAP(a, b) \{ \ a = a + b; \ b = a - b; \ a = a - b; \}Demo2:位运算形式:应用异或(两个雷同的值异或后果为0,任何数和0异或仍为自身) #define SWAP(a, b) \{ \ a = a ^ b; \ b = a ^ b; \ a = a ^ b; \}位运算符分析C语言最后设计用来开发UNIX操作系统,操作系统运行于硬件平台之上,必然会波及位运算,须要对硬件的bit位(0和1)进行操作。C语言中位运算间接映射到了硬件零碎中的位运算。位运算符间接对bit位进行操作,其效率最高。 1、C语言中的位运算符运算符意义规定&按位与全1得1,有0得0I按位或有1得1,全0得0^按位异或雷同为0,不同得1~取反1变0, 0变1<<左移高位抛弃,低位补0·>>右移高位补符号位,低位舍弃2、左移和右移的留神点左操作数必须是整数类型 char和short被隐式转换为int后进行操作右操作数的范畴必须为:[0,31],否则后果未定义(不同编译器处理结果不同)左移运算符<<将运算数的二进制位左移,成果相当于乘以2的n次方,效率更高右移运算符>>将运算数的二进制位右移,成果相当于除以2的n次方,效率更高 Demo1 d << 2; // error, 左操作数必须是整型 int x = 10 >> 1; // ok,"右移等效除以2的n次方",输入5 int y = -1 << 1; // ok,"左移等效乘以2的n次方",输入-2 int z = 3 << -1; // -1不在[0,31]范畴中,后果未定义,不同编译器不同解决 // 编译器亦提醒了谬误:Possible overflow in shift operation // gcc 1, 左移-1相当于右移1,那就除以2,失去了1 // bcc -2147483648, int的最小值 // vc 0, 原本就未定义,给你0把防止位运算符、逻辑运算符、数学运算符等混合运算,如果必须这样,应用括号示意好计算程序。(单算移比、按逻三赋) ...

October 10, 2021 · 1 min · jiezi

关于c:ELEC129-C语法解说

Department of Electrical Engineering and ElectronicsIntroduction toProgramming in C(ELEC129)Assignment 4Introduction to Programming in C (ELEC129) Assignment 4Dept. Electrical Eng. & Electronics Page 2 / 4 University of LiverpoolObjectivesTo design, implement and document modular programs that use functions and I/O files.AssessmentThis assignment is an assessed component and the mark for this work will contribute towardsthe overall module mark. The weight of Assignment 4 is 12%. The marking criteria can befound in the Exam Resources section of ELEC129 in VITAL.This assignment is composed of a number of exercises. The relative weight of each exercise onthe overall assignment mark is indicated between brackets.InstructionsStudents are required to do all exercises and submit a single Word file in the Assessmentsection of ELEC129 in VITAL (https://vital.liv.ac.uk) by Monday 04/03/2019 at 17:00 (5pm) UKlocal time (week 6 of semester 2). Delay penalties apply. Please double check your report andmake sure your work is in its final form before submission as the online application will notallow resubmissions. Email submissions and/or resubmissions will not be accepted.Submissions must be a single Word file containing the work done by the student (studentname and student ID should be clearly stated in the first page). The file must contain twoparts for each exercise proposed in this assignment as detailed below.Part I: The first part must contain the source code. Please use font Courier New with a size of 8points, use indentation to make the code readable, and observe the following requirements: The source code must be the result of your own original and individual work. The source code must be entirely written in the C programming language. Source codewritten in any other programming languages (e.g., C++) will receive a mark of zero. The use of global variables is (in general) not needed in ELEC129 assignments and itsuse is not allowed unless otherwise stated. All variables should be local to a function(i.e., declared within the body of a function). The use of global variables will bepenalised. If you are in doubt, ask a lab demonstrator to check your source code. All exercises can be solved based on concepts explained in previous lectures. Studentsare allowed to use concepts from other (future) chapters but this is not expected. Feelfree to discuss your approach to solving the exercises with a lab demonstrator.Part II: The second part must contain a detailed explanation of the software developmentprocess followed by the student (i.e., the first five steps of the software development method): ...

October 9, 2021 · 6 min · jiezi

关于c:100ASKIMX6ULLPRO开发板QT移植过程说明

百问网对于 Qt 的移植过程没有做非常具体且零碎的阐明,导致初学者的我在移植时破费了较多工夫,特此写下此文给有须要的人参考。下述阐明基于百问网提供的环境进行形容 (网上搜寻到的个别是在全新环境进行构建)。一、应用repo获取内核及工具链等1. 配置repo下载 repo 工具前须要设置git的邮箱和用户名,git邮箱和用户名请依据集体状况进行配置。 book@100ask:~$ git config --global user.email "user@100ask.com"book@100ask:~$ git config --global user.name "100ask"留神: 请先配置git邮箱和用户名,否则会导致下载失败(如下为参考示例图)。 2. 下载源码执行以下4条命令,为不便大家复制,第3条是很长的命令,应用了\来换行,须要一并拷贝: book@100ask:~$ git clone https://e.coding.net/codebug8/repo.gitbook@100ask:~$ mkdir -p 100ask_imx6ull-sdk && cd 100ask_imx6ull-sdkbook@100ask:~/100ask_imx6ull-sdk$ ../repo/repo init -u \ https://gitee.com/weidongshan/manifests.git -b \linux-sdk -m imx6ull/100ask_imx6ull_linux4.9.88_release.xml --no-repo-verifybook@100ask:~/100ask_imx6ull-sdk$ ../repo/repo sync -j4留神: 是在 book@100ask:~$ 目录下执行的操作 二、配置穿插编译工具链1. 设置穿插工具链关上配置文件 vim ~/.bashrc, 在文件开端增加以下命令 export ARCH=armexport CROSS_COMPILE=arm-buildroot-linux-gnueabihf-export PATH=$PATH:/home/book/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin设置结束后,要执行 source ~/.bashrc 命令使其失效,这条命令是加载这些设置的环境变量 2. 测试穿插工具链测试环境变量: book@100ask:~$ echo $ARCHarmbook@100ask:~$ echo $CROSS_COMPILEarm-buildroot-linux-gnueabihf-测试穿插编译器: book@100ask:~$ arm-buildroot-linux-gnueabihf-gcc -v ...

October 9, 2021 · 2 min · jiezi

关于c:C进阶15逻辑运算符

Summary1)&&表达式从左向右计算,当遇到条件为假时,整个表达式为假,前面的表达式都不再执行,是为短路规定; 2) ||表达式从左向右计算,当遇到条件为真时,整个表达式为真,前面的表达式都不再执行,是为短路规定; 3)逻辑表达式中&&比||的优先级更高,体现为:当&&和||在同一个表达式中呈现时,整个表达式被看作一个||表达式。先计算&&表达式,最初计算整个的||表达式,某个表达式为真的时候,整个||表达式就短路了。 4)C语言中的逻辑非"!"只意识0(假),其余的任何值都是非0(真)。"!"罕用于if语句中判断表达式是否为假;也可用于将一个整数变为1,如!!100; 逻辑运算符的荫蔽知识点1、&& 和 || 中的短路规定|| 从左向右开始计算:当遇到条件为真时进行计算,整个表达式为真;所有条件都为假时表达式才为假 int LogicFunc(int i){ printf("LogicFunc(int i) : %d\n", i); return i;}int main(){ if(LogicFunc(1) || LogicFunc(0)) { printf("Logic expression is true"); } else { printf("Logic expression is false"); }}输入:LogicFunc(int i) : 1Logic expression is true起因:逻辑||表达式的短路规定,第1个表达式LogicFunc(1)返回1,为true,第二个表达式因为短路规定并未执行&& 从左向右开始计算:当遇到条件为假时进行计算,整个表达式为假;所有条件都为真时表达式才为真 int LogicFunc(int i){ printf("LogicFunc(int i) : %d\n", i); return i;}int main(){ if(LogicFunc(0) && LogicFunc(1)) { printf("Logic expression is true"); } else { printf("Logic expression is false"); }}输入:LogicFunc(int i) : 0Logic expression is false起因:逻辑&&表达式的短路规定,第1个表达式LogicFunc(0)返回0,false,第二个表达式因为短路规定并未执行2、&& 和 || 混合运算时的规定逻辑表达式中&&比||的优先级更高,体现为:当&&和||在同一个表达式中呈现时,整个表达式被看作一个||表达式。先计算&&,最初计算||。 ...

October 7, 2021 · 1 min · jiezi

关于c:鸿蒙内核源码分析双向链表篇-谁是内核最重要结构体-开篇致敬鸿蒙内核开发者-v111

子曰:“见贤思齐焉,见不贤而内自省也。” 《论语》:里仁篇 百篇博客系列篇.本篇为: v01.xx 鸿蒙内核源码剖析(双向链表篇) | 谁是内核最重要构造体 根底工具相干篇为:v01.xx 鸿蒙内核源码剖析(双向链表) | 谁是内核最重要构造体v19.xx 鸿蒙内核源码剖析(位图治理) | 谁能一分钱分两半花v20.xx 鸿蒙内核源码剖析(用栈形式) | 程序运行场地由谁提供v31.xx 鸿蒙内核源码剖析(定时器) | 哪个工作的优先级最高v34.xx 鸿蒙内核源码剖析(原子操作) | 谁在为原子操作保驾护航v35.xx 鸿蒙内核源码剖析(工夫治理) | 谁是内核根本工夫单位谁是鸿蒙内核最重要的构造体?答案肯定是: LOS_DL_LIST(双向链表),它长这样. typedef struct LOS_DL_LIST {//双向链表,内核最重要构造体 struct LOS_DL_LIST *pstPrev; /**< Current node's pointer to the previous node *///前驱节点(左手) struct LOS_DL_LIST *pstNext; /**< Current node's pointer to the next node *///后继节点(右手)} LOS_DL_LIST;构造体够简略了吧,只有前后两个指向本人的指针,但恰好是因为太简略,所以才太不简略. 就像氢原子一样,宇宙中无处不在,占比最高,起因是因为它最简略,最稳固! 内核的各个模块都能看到双向链表的身影,下图是各处初始化双向链表的操作,因为太多了,只截取了局部: 很多人问图怎么来的, source insight 4.0 是浏览大型C/C++工程的必备工具,要用4.0否则中文有乱码. [下载 source insight 4.0 破解版] ...

October 7, 2021 · 3 min · jiezi

关于c:CSE-232-C语言编程

CSE 232 Spring 2019Programming Project 05Assignment OverviewThis assignment is worth 40 points (4.0% of the course grade) and must be completed and turnedin before 11:59pm on Monday, Feb 25th. That's two weeks because of the midterm on Thur, Feb14th.BackgroundSteganographySteganography (https://en.wikipedia.org/wiki...) is the process of hiding a "secretmessage" in another text file, image or even sound file. It differs from cryptography in that theoverall file/video/audio looks reasonably normal and still conveys information, making it hard totell that there is a secret hidden inside. We are going to write a steganographic encoder/decoderfor text.A Simple SteganographyWe are going to take a plaintext message, one that anyone can read, and embed in that message asecret message which someone, who knows the code, can decipher.The process is this. We are going to take the plaintext message, reduce the plaintext message toall lower case, then encode the secret message in the plaintext based on combinations ofUPPER or lower case. Thus it is the sequence of upper and lower case letters in the plaintextmessage that encode our secret message.We do this as follows. Each individual letter of the secret message is turned into a binary stringof 5 0's and 1's. Exactly 5 for each letter. We will only recognize letters and will ignore any othercharacters in the secret message. For each of these binary strings, we take the next 5 letters of theplaintext and modify them as follows: for every 0 in the secret message binary string we lowercase the plaintext letter, for every 1 we upper case the letter. We do this only for letters, ignoringall other characters in the plaintext. Let's consider the following example. The secret message is"help " and the original text is "Mom please send more money!" The index of each letter is itsposition in the alphabet with 'a' at 0, 'z' at 25.Secret letter 'h' 'e' 'l' 'p'Letter index 7 4 11 15binary 00111 00100 01011 01111Encoded 5 letters moM PL eaSe s eNd MO rE MONThe new message, with the encoded secret message would be (hard to write with autocorrect)"moM PLeaSe seNd MOrE MONey!". As we said, we can only capitalize letters so we ignore(don’t count as one of the 5 letters) any other character in the plaintext message which just getspassed through unaltered.Reverse the process for decoding: take 5 letters from the encoded plaintext, ignoring any othercharacters, determine the binary string the capitalization indicates, and add the new letter thatbinary string represents as the next letter of the secret message.Rules of the Process. we ignore non-alphabetic characters in the plaintext and pass them through to theencoded text as is. we also ignore any non-alphabetic characters in the secret message. Those non-alphabeticcharacters will not be encoded. Thus spaces will be lost in decoding the secret message,as will any numbers of punctuation marks. if there are "left over" letters in the plaintext, letters we do not require to encode a portionof the secret message) we just pass them through into the encoded text unchanged. if there are not enough letters in the plaintext to encode the secret message, that is anerror condition and we indicate as such and quit. We mentioned that, if there are more letters than necessary to encode the secret messagein the plaintext, then we just pass the "extra" letters through. On decoding that may creategarbage at the end of our decoded message. That’s OKASCIIAs a note, you don't need a string to turn a letter into an index number. The index order of anascii letter can be found by subtracting the character 'a' from any other lower-case letter. Thusthe letter 'f' is index 5, found by 'f' – 'a' . You did this in lab last week.Program Specificationsstring lower_case(string s) returns the lower case version of the input string s, that is all alphabetic characters areconverted to lower case.string to_binary(char c) returns 5 bit string that is the index of the character argument.o if the provided character is not a lower-case alphabetic character, return the emptystring.char from_binary(string bit_str) returns the character that the 5 bit binary string bit_str represents.o if any of the following conditions are not true: the size of bit_str is 5 every element of bit_str must be a ‘1’ or a ‘0’ the character produced must be a lower case letter return the character 0 (the NULL char).bool check_message(string plaintext, string secret_message) returns true if there are at least 5x the count of characters in secret_message as inplaintext, false otherwise? Remember, only alphabetic characters matter, all other characters in the plaintext areignored. We are counting whether there are enough useable characters in plaintext.string encode(string plaintext, string secret_message) plaintext and secret_message should be converted to lower case by lower_case the plaintext string should have been checked by check_messageo if check_message is false, return the string "Error". otherwise returns encoded_text encoded (as described) with the secret_message.string decode(string to_decode) returns the original secret_message as a string.o if there were more characters in to_decode than 5*characters in thesecret_message, you will get extra ‘a’ characters at the end of the decodedmessage.o if the number of characters in to_decode is not a multiple of 5, it will be ragged.By that I mean that you will get 4 or less characters at the end of to_decode. Sincewe cannot turn those characters into a secret_message character (we need 5),they should be ignored.DeliverablesYou will turn in one file: proj05_functions.cpp inside a directory names proj05 .Weprovide you with proj05_functions_05.h , as well as a main proj05_main.cpp youcan use to test your functions. However, Mimir can test the individual functions without a mainprogram which is how the tests are structured. It is still a good idea for you to test your own codewith a main. This will be the last time we provide you with a main you can use to test yourfunctions. You should start doing that yourself.Remember to include your section, the date, project number and comments and you do notprovide main.cpp. If you turn in a main with your code Mimir it will be ignored. ...

October 6, 2021 · 6 min · jiezi

关于c:C语言实现三子棋

C语言实现三子棋(通过数组)须要蕴含的头文件 include <stdio.h>include <stdlib.h>include <time.h>创立一个全局数组因为如果数组大小变动,游戏规则和实现思路都会有很大的变动,所以不进行宏定义常量来定义数组char board3;设计主程序框架game()函数为游戏过程框架int main(){ do{ int i = 0; printf("1.Start the game\n"); printf("2.Quit the game\n"); printf("Please enter your options->"); scanf("%d", &i); switch (i) { case 1: game(); //game()函数为游戏过程框架 break; case 2: return 0; default: printf("Input error,please enter again!\n"); break; }} while(1);}设计游戏过程框架void game(){ initBoard();srand((unsigned)time(NULL)); //生成随机种子,前面须要生成随机坐标char temp = ' '; //定义一个字符变量,用于接管前面判断函数返回值,用于决定游戏输赢do{ printBoard(); //打印棋盘的函数 userPlay(); //玩家下棋的函数 temp = judge(); //判断游戏是否分出输赢 if (temp != ' ') break; robotPlay(); //电脑下棋的函数 temp = judge();} while (temp == ' ');printBoard();switch (temp){ case '@': printf("User WIN!\n"); break; case '$': printf("Bobot WIN!\n"); break; case '*': printf("Dogfall !\n"); break; dafault: break;}}设计棋盘款式有趣味的能够搞的更加花里胡哨,这里草草了事,呸,简略设计一下 哈//##########// | | //_|_|_// | | //_|_|_// | |//##########打印棋盘重点就在这了,棋盘设计的再牛逼,也得能打印进去才行这里棋盘设计的比拟繁难,打印起来也比较简单,要害是思路要清晰void printBoard(){ ...

October 3, 2021 · 2 min · jiezi

关于c:c学习笔记-Dynamic-Thesky

1.int整型相除后果取整舍小数 2.两个小数不能做取模运算 3.前置递增++a:让变量a(此处为a)+1 前置与后置递增的区别:前置先让变量+1而后进行表达式运算 4.非真即假,a=10,10>0为真;!a=0,a取反则为假即为0,!!a非假值为1(非零则为真) 5.switch语句中只能放整型或字符 6.while循环当条件为真时才执行,在"输入0-9"的实例中,当num实现while循环后其值为10 7.rand() % 100 //此处将会随机生成一个0-99的数字(rand为伪随机) 8.获取三位数的个位:对数字取模于10十位:先整除10在取模于10(解析:先转化为两位数在进行获取个位数的操作)百位:除以100 9.若应用优化好的支流编译器则在循环内定义变量不会被反复调配 10.嵌套循环中的i能够重复使用,可能是独立于循环中的,编译器容许套娃,然而最好不要,会升高程序可读性.(套娃循环) 11.嵌套循环中输入的雷同的变量(例如i),存在就近准则,即输入最近的i 12.在初始化数组数据的时候,没有填写的数据(间断的开端的数)会用0补充 13.内存地址是随机调配 ,每次运行都会产生扭转 14.数组名是常量不能进行赋值 15.指针本质是用于保留地址的变量,但因起非凡用处所以另起概念,某种层面上:指针==变量==地址 16.&:取址 *取值,指针在指向数组的时候可不加&//详见第29条,在指向数组中某一元素的时候用& 17.解援用: 把地址对应的内容解进去,并 援用 ; 即p== p(指针)对应(或指向)的内容(p就是p对用内容的援用) 18.空指针好比:int a = 0,然而指针开始的时候没有地址给他"指",指向null就和给a赋的值0的意义差不多 19.函数中参数为数组时,数组主动进化成数组中第一个数据的首地址,:arr[i] == *(arr+i)即拜访arr[第一个数据+i]中的数据;这也是为什么i<len(数组长度)的起因,因为传递的形参是第一个数据的地址,此时数组的数据个数就等于len-1.(留神点:第一个数组计数点为0;用数组长度//假设为3;求最初一个元素则示意为3-1//0,1,2中2是最初一个元素,但他有三个元素所以须要减1) 20.构造体:创立构造体变量的时候关键字可省略,而构造体变量定义的时候不可省略 21.在main()函数里定义的同名变量会屏蔽掉main函数外的全局变量,(在外定义的是全局在内定义的是部分,) 22.当局部变量被定义时,零碎不会对其初始化,您必须自行对其初始化。定义全局变量时,零碎会主动初始化为下列值[int 0char ''float、double 0.0pointer nullptr (C语言是NULL)//NULL和nullptr在指针层面上代表的都是空值,然而因为Null自身是宽泛意义上的空值(0之类的)所带来的在c++上的局限性,c++定义了一种新的专门的空指针值类型] 23.在函数内应用同名的全局变量和局部变量:在全局变量之前加上域名解析则援用全局变量(::a是全局)24.static润饰的全局动态变量只在以后源文件内应用;动态修饰符用于将函数内的值从栈区放到全局区(不会因为来到作用域而被开释或回收掉),变为全局变量,能够返回该变量并可在内部操作该变量 25.在一个文件中有某变量的定义,则在其余应用到该变量的文件中应申明该变量(此时不可赋值) 26.一般数组中以数组名用cout来输入,只会失去一串地址;用字符数组则会输入数组中的内容. 27.指针不同的数据类型指向的变量或常量的数据类型不同,能够记为:某类型的指针指向同类型的数据 28.形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参自身进行的操作 &height[0] 就是获得是数组第一个元素的地址,假如地址为 1000;&height 是间接对数组名进行取地址,这个时候就是获得是 height 整个数组的地址,指向蕴含 10 个元素的 int 型数组,height 等价于 &height[0],height+1 会将地址加 4 个字节(不肯定是四个,视类型而定);但 &height+1 就是将地址减少 10*4 个字节(取地址符优先级大于加号个,故取地址符依照其结合律先与height联合之后对联合值进行加1操作)30.传递参数和传递地址的区别:传递参数时复制实参,如果传入数据过多会影响执行效率;当传递参数过多时应用传递地址,这样只传入四个字节,或者用facetoface 31.类的权限分为:私有、公有、爱护权限,私有权限类内和类外都能够拜访,爱护和公有只能类内拜访(区别在于爱护权限子对象也能够拜访,而公有权限子对象不能够拜访),类内拜访即应用构造函数:例如在函数体内应用赋值语句"属性 = 内部变量",而后通过调用该函数实现类内拜访 ...

October 3, 2021 · 1 min · jiezi

关于c:在写矩阵转换时发现的一个for循环括号的问题

在写矩阵转换时发现的一个for循环的问题最近在写c语言作业的一个矩阵转换的时候,程序运行没有问题,但输入总是存在问题。起初与敌人探讨了一下,最初发现问题存在于for循环的括号问题。以此记录一下,不便学习。 以上是问题代码,输入后果如下 咱们来细分一下代码 #include <stdio.h>int main(){ int i,j,t; int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; for(i=0;i<3;i++) for(j=0;j<3;j++) printf("%d",a[i][j]); /*输入原始矩阵*/ printf("\n"); 以下为该代码输入后果 为什么会呈现这样呢?在c primer外面讲述for循环的定义是这样的: for(condition1;condition2;condition3) statement也就是说执行主体的完结靠的是statement的完结,即一个语句的完结。天然,下面的代码它只思考了第二个for循环外面的printf语句,而没有执行转行命令。(\n) 在存在多个逻辑语句的状况下,for循环外面须要用到大括号,即:{} 咱们扭转一下代码,试试看 for(i=0;i<3;i++) for(j=0;j<3;j++) { printf("%d",a[i][j]); /*输入原始矩阵*/ printf("\n"); }后果如下: 很显著,咱们在第二个for循环外面加了大括号,换行指令立即在第二个for循环中执行了。 咱们再改一下,看一看。 for(i=0;i<3;i++){ for(j=0;j<3;j++) printf("%d",a[i][j]); /*输入原始矩阵*/ printf("\n");}输入后果如下: 很显著,在整体的for循环外面(第一个for循环),它先执行了第二个for循环外面的指令,在第二个for循环外面的指令实现了,实现了换行。 一个清晰明了的例子: 很显著,他是先遍历完一个for才输入test的,阐明test的输入语句和遍历输入不在一个for下的。 总之,咱们都要养成写一个工整代码的习惯,这不仅是为了不便他人查看,更是为了日后咱们了解本人的代码,比方我当初写代码的时候,根本在for循环都会加个括号,这样会不便我了解代码是在哪个模块运行的。同时,缩进也显得十分重要,对于你了解本人的代码来说。 感激:DynamicLab - The_sky

October 3, 2021 · 1 min · jiezi

关于c:uint32t考据

uint32_t: u=unsigned(无符号); int=integer(整数); 32=32bits(32位); t=typedef。 这是从C99起定义于<stdint.h>中的"定宽整数类型(Fixed-width integer types)"1。 相似的共有四个: uint8_t, uint16_t, uint32_t, uint64_t,是出于跨平台的须要。 Fixed width integer types (since C99) ↩

October 1, 2021 · 1 min · jiezi

关于c:C进阶14单引号和双引号

Summary1)C语言中的单引号用来示意字符字面量;字符字面量的实质是一个整数; 2)C语言中的双引号用来示意字符串字面量;字符串字面量的实质是一个指针(内存地址); 3)低于0x08048000这个值的内存地址都是不能间接拜访的,拜访就会段谬误; 4)留神:char类型和char*类型要用正确的字面量进行初始化;尽管char a = ""; char* s = 'a';都能编译的过,但应用的时候就会出意想不到的段谬误。 5)字符字面量和字符串字面量的混同应用在C编译器中能够编的过,但要留神warning,工程中对于所有的warning肯定都要当成error来解决。 单引号和双引号C语言中的单引号用来示意字符字面量;字符字面量的实质是一个整数,'a'在内存中占1个字节,'a'+1 示意'a'的ASCII码值加1,后果为'b'。 C语言中的双引号用来示意字符串字面量;字符串字面量的实质是一个内存地址(地址值),"a"在内存中占有2个字节,"a"+1 示意指针运算,后果指向"a"中的结束符'\0'。 代码浏览: char* p1 = 1;char* p2 = '1';char* p3 = "1";printf("%s, %s, %s", p1, p2, p3);printf('\n');printf("\n");代码解析: p1 用一个整数字面量1进行初始化,有warning,但能够编的过,因为指针实质也是一个32(64)位的整数值p2 用一个字符字面量'1'进行初始化,同p1。字符'1'实质也是一个整数,值为49p3 用一个字符串字面量"1"进行初始化,字符串字面量的实质是一个指针(内存地址),没有问题printf(param1, ...)的第一个参数是一个指针,地址值printf('\n')能够编的过,然而warning,同p2,应用10作为一个地址值传给printf函数printf("\n")能够编的过,应用一个字符串字面量作为参数,换行综上:p1 p2 printf('\n')都是能够编的过,然而有问题的语句,在进行打印的应用就会段谬误,因为应用了谬误的地址值,拜访了不该拜访的内存,野指针!!! 代码浏览: char c = " "; while(c == "\t" || c == " " || c == "\n") { scanf("%c", &c); }代码解析: c的初始化:应用一个只有空格字符的字符串字面量进行初始化;实际上是用一个指针(内存地址值)进行初始化因为char类型占1个字节,指针类型占4字节(32位),所以会产生截断再去进行while循环的判断,第一次就为false,不会进到循环中所以要正确判断字符类型和字符串类型,确保应用的类型是正确的:批改,将"\t"等都改成'\t'。本文总结自“狄泰软件学院”唐佐林老师《C语言进阶课程》。如有错漏之处,恳请斧正。

September 25, 2021 · 1 min · jiezi

关于c:程序人生-C-语言编译器对内存空间的分配原则

本文首发于 2015-05-04 14:50:16概述一个由 C/C++ 编译的程序占用的内存分为以下几个局部: 栈区(stack):由编译器主动调配、开释,寄存函数的参数值、局部变量的值等,其操作形式相似于数据结构中的栈。个别大家常说的堆栈和栈是一样的,就是栈(stack),而说 堆 时才是堆 heap 。 堆区(heap):个别由程序员调配开释,若程序员不开释,程序完结时由OS回收。留神它与数据结构中的堆是两回事,调配形式倒是相似于链表。全局区(动态区,static):全局变量和动态变量的存储是放在一块的,初始化的全局变量和动态变量在一块区域,未初始化的全局变量和未初始化的动态变量在相邻的另一块区域。程序完结后由零碎开释。文字常量区:常量字符串就是放在这里的。程序完结后由零碎开释。程序代码区:寄存函数体的二进制代码。举例来说: //main.cpp int a = 0; // 全局初始化区 char *p1; // 全局未初始化区 main() { int b; // 栈 char s[] = "abc"; // 栈 char *p2; // 栈 char *p3 = "123456"; // 123456\0 在常量区,p3在栈上。 static int c =0; // 全局(动态)初始化区 // 调配的 10 个和 20 个字节的区域就在堆区。 p1 = (char *)malloc(10); p2 = (char *)malloc(20); strcpy(p1, "123456"); // 123456\0 放在常量区,编译器可能会将它与p3所指向的"123456"优化成同一个地位} 在函数体中定义的变量通常是在栈上,用malloc, calloc, realloc等分配内存的函数调配失去的就是在堆上。 ...

September 25, 2021 · 1 min · jiezi

关于c:程序人生-UNIX-网络编程之-getaddrinfo-函数详解及使用举例

本文首发于 2015-01-03 21:04:36概述IPv4 中应用 gethostbyname() 函数实现主机名到地址解析,这个函数仅仅反对 IPv4 ,且不容许调用者指定所需地址类型的任何信息,返回的构造只蕴含了用于存储 IPv4 地址的空间。 IPv6中引入了getaddrinfo()的新API,它是协定无关的,既可用于 IPv4 也可用于IPv6 。 getaddrinfo函数可能解决名字到地址以及服务到端口这两种转换,返回的是一个addrinfo的构造(列表)指针而不是一个地址清单。这些addrinfo构造随后可由socket函数间接应用。 getaddrinfo函数把协定相关性平安暗藏在这个库函数外部。应用程序只有解决由getaddrinfo函数填写的套接口地址构造。该函数在 POSIX标准中定义了。 函数阐明蕴含头文件: #include <sys/types.h>#include <sys/socket.h>#include <netdb.h>函数原型: int getaddrinfo( const char *hostname, const char *service, const struct addrinfo *hints, struct addrinfo **result );参数阐明: hostname: 一个主机名或者地址串(IPv4 的点分十进制串或者 IPv6 的 16 进制串)。service:服务名能够是十进制的端口号,也能够是已定义的服务名称,如 ftp、http 等。hints:能够是一个空指针,也能够是一个指向某个 addrinfo 构造体的指针,调用者在这个构造中填入对于冀望返回的信息类型的暗示。result:本函数通过 result 指针参数返回一个指向 addrinfo 构造体链表的指针。返回值: 0:胜利;非0:出错。 参数设置在getaddrinfo函数之前通常须要对以下6个参数进行以下设置:nodename、servname、hints的ai_flags、ai_family、ai_socktype、ai_protocol。 在6项参数中,对函数影响最大的是nodename,sername和hints.ai_flag,而ai_family只是有地址为v4地址或v6地址的区别。ai_protocol个别为0不作改变。 getaddrinfo在理论应用中的几种罕用参数设置: 个别状况下,client/server编程中,server端调用bind(如果面向连贯的还须要listen);client则无需调用bind函数,解析地址后间接connect(面向连贯)或间接发送数据(无连贯)。因而,比拟常见的状况有: 通常服务器端在调用getaddrinfo之前,ai_flags设置AI_PASSIVE,用于bind;主机名nodename通常会设置为NULL,返回通配地址[::]。客户端调用getaddrinfo时,ai_flags个别不设置AI_PASSIVE,然而主机名nodename和服务名servname(更违心称之为端口)则应该不为空。当然,即便不设置AI_PASSIVE,取出的地址也并非不能够被bind,很多程序中ai_flags间接设置为0,即3个标记位都不设置,这种状况下只有hostname和servname设置的没有问题就能够正确bind。上述情况只是简略的client/server中的应用,但理论在应用getaddrinfo和查阅国外开源代码的时候,曾遇到一些将servname(即端口)设为NULL的状况(当然,此时nodename必不为NULL,否则调用getaddrinfo会报错)。 应用须知1)如果本函数返回胜利,那么由result参数指向的变量已被填入一个指针,它指向的是由其中的ai_next成员串联起来的addrinfo构造链表。 struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; size_t ai_addrlen; struct sockaddr *ai_addr; /* 我认为这个成员是这个函数最大的便当。 */ char *ai_canonname; struct addrinfo *ai_next; };其中,sockaddr构造体为: ...

September 25, 2021 · 5 min · jiezi

关于c:程序人生-C语言字节对齐问题详解-对齐字节序位序网络序等下

本文首发于 2014-07-21 15:35:306. 附录6.1. 字节序与网络序6.1.1. 字节序字节序,顾名思义就是字节的高下位寄存程序。 对于单字节,大部分处理器以雷同的程序解决比特位,因而单字节的寄存和传输方式个别雷同。 对于多字节数据,如整型(32位机中个别占4字节),在不同的处理器的寄存形式次要有两种(以内存中 0x0A0B0C0D 的寄存形式为例)。 6.1.1.1. 大字节序(Big-Endian,又称大端序或大尾序)在计算机中,存储介质以上面形式存储整数 0x0A0B0C0D,则称为大字节序: 数据以8bit为单位:低地址方向 -> 0x0A 0x0B 0x0C 0x0D -> 高地址方向 数据以16bit为单位:低地址方向 -> 0x0A0B 0x0C0D -> 高地址方向 其中,最高无效位(MSB,Most Significant Byte)0x0A存储在最低的内存地址处。下个字节0x0B存在前面的地址处。同时,最高的16bit单元0x0A0B存储在低位。 简而言之,大字节序就是高字节存入低地址,低字节存入高地址。 这里讲个词源典故:“endian”一词来源于乔纳森·斯威夫特的小说《格列佛游记》。小说中,小人国为水煮蛋该从大的一端(Big-End)剥开还是小的一端(Little-End)剥开而争执,争执的单方别离被称为 Big-endians 和 Little-endians 。 1980年,Danny Cohen在其驰名的论文"On Holy Wars and a Plea for Peace"中为平息一场对于字节该以什么样的程序传送的争执而援用了该词。 借用下面的典故,设想一下要把熟鸡蛋旋转着稳立起来,大头(高字节)必定在上面(低地址)^_^ 6.1.1.2. 小字节序(Little-Endian,又称小端序或小尾序)在计算机中,存储介质以上面形式存储整数 0x0A0B0C0D 则称为小字节序: 数据以8bit为单位:高地址方向 -> 0x0A 0x0B 0x0C 0x0D -> 低地址方向 数据以16bit为单位:高地址方向 -> 0x0A0B 0x0C0D -> 低地址方向 其中,最低无效位(LSB,Least Significant Byte)0x0D存储在最低的内存地址处。前面字节顺次存在前面的地址处。同时,最低的16bit单元0x0A0B存储在低位。 可见,小字节序就高字节存入高地址,低字节存入低地址。 C语言中的位域构造也要遵循比特序(相似字节序) 。例如: ...

September 25, 2021 · 5 min · jiezi

关于c:程序人生-UNIX环境高级编程技巧之-du-指令实现

本文首发于 2014-07-10 10:00:41代码#include <stdio.h>#include <stdlib.h>#include <glob.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#define PATHSIZE 1024static int path_noloop(const char *path){ char *pos; pos = strrchr(path,'/');//定位最左边的'/'的地位 if(strcmp(pos+1,".") == 0 || (strcmp(pos+1,"..") == 0)) return 0; return 1;}static int64_t mydu(const char *path){ int i; glob_t globres; int64_t sum; static struct stat statres; static char nextpath[PATHSIZE]; if(lstat(path, &statres) < 0) { perror("lstat()"); return 0;//exit(1); } if(!S_ISDIR(statres.st_mode)) return statres.st_blocks; strncpy(nextpath, path,PATHSIZE); strncat(nextpath, "/*" , PATHSIZE); glob(nextpath,GLOB_NOSORT, NULL, &globres); strncpy(nextpath, path,PATHSIZE); strncat(nextpath, "/.*" , PATHSIZE); glob(nextpath,GLOB_NOSORT|GLOB_APPEND, NULL, &globres); sum = statres.st_blocks; for(i = 0 ;i < globres.gl_pathc ; i++) { if(path_noloop(globres.gl_pathv[i])) sum += mydu(globres.gl_pathv[i]); } return sum;}int main(int argc,char **argv){ if(argc < 2) { fprintf(stderr,"Usage...\n"); exit(1); } printf("%lld 512B blocks\n", (long long int)mydu(argv[1])); return 0;}编译$ gcc -g -Wall testdu.c -o testdu运行testdf执行成果:$ ./testdu /usr/bin1766184 512B blocks原生df执行成果:$ du -sh /usr/bin859M /usr/bin欢送关注我的微信公众号【数据库内核】:分享支流开源数据库和存储引擎相干技术。 ...

September 25, 2021 · 1 min · jiezi

关于c:程序人生-C语言字节对齐问题详解-对齐字节序位序网络序等上

本文首发于 2014-07-21 15:32:281. 引言思考上面的构造体定义: typedef struct{ char c1; short s; char c2; int i;}T_FOO;假如这个构造体的成员在内存中是紧凑排列的,且c1的起始地址是0,则s的地址就是1,c2的地址是3,i的地址是4。 当初,咱们编写一个简略的程序: int main(void){ T_FOO a; printf("c1 -> %d, s -> %d, c2 -> %d, i -> %d\n", (unsigned int)(void*)&a.c1 - (unsigned int)(void*)&a, (unsigned int)(void*)&a.s - (unsigned int)(void*)&a, (unsigned int)(void*)&a.c2 - (unsigned int)(void*)&a, (unsigned int)(void*)&a.i - (unsigned int)(void*)&a); return 0;}运行后输入: c1 -> 0, s -> 2, c2 -> 4, i -> 8为什么会这样?这就是字节对齐导致的问题。 本文在参考诸多材料的根底上,具体介绍常见的字节对齐问题。因成文较早,材料起源大多已不可考,敬请体谅。 2. 什么是字节对齐古代计算机中,内存空间依照字节划分,实践上能够从任何起始地址拜访任意类型的变量,但实际上在拜访特定类型变量时常常在特定的内存地址拜访,这就须要各种类型数据依照肯定的规定在空间上排列,而不是一个接一个地程序寄存,这就是对齐。 3. 对齐的起因和作用不同硬件平台对存储空间的解决上存在很大的不同。某些平台对特定类型的数据只能从特定地址开始存取,而不容许其在内存中任意寄存。例如 Motorola 68000 处理器不容许16位的字寄存在奇地址,否则会触发异样,因而在这种架构下编程必须保障字节对齐。如果不依照平台要求对数据寄存进行对齐,会带来存取效率上的损失。比方32位的 Intel 处理器通过总线拜访(包含读和写)内存数据。每个总线周期从偶地址开始拜访32位内存数据,内存数据以字节为单位寄存。如果一个32位的数据没有寄存在4字节整除的内存地址处,那么处理器就须要2个总线周期对其进行拜访,显然拜访效率降落很多。因而,通过正当的内存对齐能够进步拜访效率。 为使CPU可能对数据进行快速访问,数据的起始地址应具备“对齐”个性。比方4字节数据的起始地址应位于4字节边界上,即起始地址可能被4整除。正当利用字节对齐还能够无效地节俭存储空间。但要留神,在32位机中应用1字节或2字节对齐,反而会升高变量访问速度,因而,须要思考处理器类型。同时,还应思考编译器的类型,在VC/C++和GNU GCC中都是默认是4字节对齐。4. 对齐的分类和准则本大节次要基于 Intel X86 架构介绍构造体对齐和栈内存对齐,位域实质上为构造体类型。 ...

September 25, 2021 · 4 min · jiezi

关于c:程序人生-我的C陷阱与缺陷读书笔记

本文首发于 2014-08-04 17:56:55第一章 词法“陷阱”1. =不同于==if(x = y) break;实际上是将y赋给x,再查看x是否为0。 如果真的是这样预期,那么应该改为: if((x = y) != 0) break;2. &和| 不同于 && 和 ||3. 词法剖析中的“贪婪法”编译器将程序分解成符号的办法是:从左到有一个一个字符的读入,如果该字符可能组成一个符号,那么再读入下一个字符,判断曾经读入的两个字符组成的字符床是否可能是一个符号的组成部分;如果可能,持续读入下一个字符,反复上述判断,直到读入的字符组成的字符串已不再可能组成一个有意义的符号。例如: y = x/*p; 会被解析为:/* 正文符号4. 整型常量010(八进制数) 不同于 10(十进制)。 5. 字符与字符串首先是单引号与双引号的区别: 用单引号括起来的一个字符示意一个整数(ASCII码),而双引号括起来示意一个指针。第二章 语法“陷阱”1. 了解函数申明弄懂(*(void(*)())0)(); //首地址为0的函数。 float (*h)(): h是一个指向返回值为浮点型的函数的指针 所以,(float (*)()) 示意一个“指向返回值为浮点型的函数的指针”的类型转换符。 fp(): 是(*fp)( )的简写。 *fp(): 是 *( (*fp) ( ) )的简写。 ( *0 )( );尽管上式编译器不认,但能够把0转换为指向“返回值为void的”函数的指针,所以0可变为: ( void(*) ( ) ) 0 ,代入(*0)(),失去: (*( void(*) ( ) ) 0) ( )该式子用等价于: ...

September 25, 2021 · 2 min · jiezi

关于c:程序人生-UNIX环境高级编程技巧之-df-指令实现

本文首发于 2014-07-10 09:48:48代码#include <stdio.h>#include <mntent.h>#include <string.h>#include <sys/vfs.h>static const unsigned long long G = 1024*1024*1024ull;static const unsigned long long M = 1024*1024;static const unsigned long long K = 1024;static char str[20];char* kscale(unsigned long b, unsigned long bs){ unsigned long long size = b * (unsigned long long)bs; if (size > G) { sprintf(str, "%0.2f GB", size/(G*1.0)); return str; } else if (size > M) { sprintf(str, "%0.2f MB", size/(1.0*M)); return str; } else if (size > K) { sprintf(str, "%0.2f K", size/(1.0*K)); return str; } else { sprintf(str, "%0.2f B", size*1.0); return str; }}int main(int argc, char *argv[]){ FILE* mount_table; struct mntent *mount_entry; struct statfs s; unsigned long blocks_used; unsigned blocks_percent_used; const char *disp_units_hdr = NULL; mount_table = NULL; mount_table = setmntent("/etc/mtab", "r"); if (!mount_table) { fprintf(stderr, "set mount entry error\n"); return -1; } disp_units_hdr = " Size"; printf("Filesystem %-15sUsed Available %s Mounted on\n", disp_units_hdr, "Use%"); while (1) { const char *device; const char *mount_point; if (mount_table) { mount_entry = getmntent(mount_table); if (!mount_entry) { endmntent(mount_table); break; } } else continue; device = mount_entry->mnt_fsname; mount_point = mount_entry->mnt_dir; //fprintf(stderr, "mount info: device=%s mountpoint=%s\n", device, mount_point); if (statfs(mount_point, &s) != 0) { fprintf(stderr, "statfs failed!\n"); continue; } if ((s.f_blocks > 0) || !mount_table ) { blocks_used = s.f_blocks - s.f_bfree; blocks_percent_used = 0; if (blocks_used + s.f_bavail) { blocks_percent_used = (blocks_used * 100ULL + (blocks_used + s.f_bavail)/2 ) / (blocks_used + s.f_bavail); } /* GNU coreutils 6.10 skips certain mounts, try to be compatible. */ if (strcmp(device, "rootfs") == 0) continue; if (printf("\n%-20s" + 1, device) > 20) printf("\n%-20s", ""); char s1[20]; char s2[20]; char s3[20]; strcpy(s1, kscale(s.f_blocks, s.f_bsize)); strcpy(s2, kscale(s.f_blocks - s.f_bfree, s.f_bsize)); strcpy(s3, kscale(s.f_bavail, s.f_bsize)); printf(" %9s %9s %9s %3u%% %s\n", s1, s2, s3, blocks_percent_used, mount_point); } } return 0;}编译$ gcc -g -Wall testdf.c -o testdf运行testdf执行成果:$ ./testdfFilesystem Size Used Available Use% Mounted onudev 3.87 GB 0.00 B 3.87 GB 0% /devtmpfs 796.17 MB 980.00 K 795.21 MB 0% /run/dev/vda1 96.75 GB 40.54 GB 56.19 GB 42% /tmpfs 3.89 GB 0.00 B 3.89 GB 0% /dev/shmtmpfs 5.00 MB 0.00 B 5.00 MB 0% /run/locktmpfs 3.89 GB 0.00 B 3.89 GB 0% /sys/fs/cgroup/dev/vda15 104.35 MB 3.86 MB 100.50 MB 4% /boot/efi/dev/loop1 55.50 MB 55.50 MB 0.00 B 100% /snap/core18/2074/dev/loop2 70.62 MB 70.62 MB 0.00 B 100% /snap/lxd/16922/dev/loop4 70.38 MB 70.38 MB 0.00 B 100% /snap/lxd/21029/dev/loop5 32.38 MB 32.38 MB 0.00 B 100% /snap/snapd/12704tmpfs 796.17 MB 980.00 K 795.21 MB 0% /run/snapd/nstmpfs 796.17 MB 0.00 B 796.17 MB 0% /run/user/1000/dev/loop6 55.50 MB 55.50 MB 0.00 B 100% /snap/core18/2128/dev/loop0 32.38 MB 32.38 MB 0.00 B 100% /snap/snapd/12883原生df执行成果:$ df -hFilesystem Size Used Avail Use% Mounted onudev 3.9G 0 3.9G 0% /devtmpfs 797M 980K 796M 1% /run/dev/vda1 97G 41G 57G 42% /tmpfs 3.9G 0 3.9G 0% /dev/shmtmpfs 5.0M 0 5.0M 0% /run/locktmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup/dev/vda15 105M 3.9M 101M 4% /boot/efi/dev/loop1 56M 56M 0 100% /snap/core18/2074/dev/loop2 71M 71M 0 100% /snap/lxd/16922/dev/loop4 71M 71M 0 100% /snap/lxd/21029/dev/loop5 33M 33M 0 100% /snap/snapd/12704tmpfs 797M 0 797M 0% /run/user/1000/dev/loop6 56M 56M 0 100% /snap/core18/2128/dev/loop0 33M 33M 0 100% /snap/snapd/12883欢送关注我的微信公众号【数据库内核】:分享支流开源数据库和存储引擎相干技术。 ...

September 23, 2021 · 3 min · jiezi