What to consider when writing portable C? [closed] - c

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I'm starting a pet project, aimed at portability. It's a simple platform game and i'm planning to compile this to many different platforms with different toolchains. The video/input/system stuff is already abstracted by having multiple video drivers, which i include based on ifdef's around my code. Each platform makefile has a define of the platform (DC, NDS, PSP, etc.) and then i include the proper video drivers, which are C files with various functions called around my code.
However, i'm not sure about other caveats of portable applications in C. Should i redefine stuff from the stdlib? u8, u16, u32 and s8, s16, s32, etc? What knowledge can you share with me for this project?

A portable program is a program that:
only uses the features of the language and library defined in the C Standard
does not invoke undefined behavior
does not depend on unspecified or implementation defined behavior.
For a list of undefined, unspecified and implementation defined behaviors, you can go the C Standard C11, Appendix J (Portability issues).

Writing in C is more or less portable as long as you make no suppositions about the sizes of your types and the pointers you use to access them. I personally prefer using the types defined in stdint.h (http://pubs.opengroup.org/onlinepubs/7999959899/basedefs/stdint.h.html) - this defines like uint8_t, uint16_t ... - but feel free to research more alternatives, such as types.h (from POSIX Standard: 2.6 Primitive System Data Types) which defines them as u_int8_t etc ...
Possibly, you will end up at the end defining your own types based on what you managed to mangle together from the various sources found on the net ... such as: game_int_16 ,game_int_32 ...

Related

Why does ISO/IEC 9899 not standardize the definitions of the functions in the C standard library? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
ISO:IEC 9899 standardizes the prototypes of the functions of the C standard library and describes their behavior. It specifies the identifier, the return type and the parameter(s) with its matching type(s) of a certain C standard function.
But why it does not specify the definitions - (the core how the specific functions actually do work)?
Why can a C standard library function X differ in its actual source code between f.e. the gcc compiler suite on Linux (GNU C Library), clang suite on macOS and the core system dynamic libraries for Microsoft Visual C++ on Windows? Why is it dependent upon the implementation, the operation system and the relative compiler design?
Edit:
I know the question seems bad for the most of yours at the first sight but it has definitely a right to get answered, since I don´t know the reason for that yet.
I do not suggest that the ISO shall standardize the definitions because the question was closed as opinion-based - don´t get me wrong. I just ask why are things that way and want to learn from your knowledge and experience.
Take strlen for example. If the ISO C standard standardized the definition of this function, it would probably look like this:
size_t strlen(char *s)
{
size_t l = 0;
while(s[l]) l++;
return l;
}
This is highly inefficient. The GNU C library has implementations written in assembly and C that are very fast, but aren't portable.
Some functions may be impossible to standardize. For example, how would it define putchar, vfprintf, and fwrite? What about assembly functions like longjmp? Or "macros" like setjmp?
Other definitions may be exploited. For example, if the Standard C committee standardizes memcpy, two things would happen:
people can abuse the copy order, and
existing implementations would be invalidated.

Subtle difference between Fortran and c with respect to how sources are interfaced and compiled together [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Both languages have a way for a single program/library to span over multiple files. C languages use include statements using explicitly created header files, whereas Fortran has the compiler generate an interface from a single module. Forgive me in advance if I misunderstood how either language compiles its source code.
In c/c++ programs you usually create .c files containing source code, and .h files containing the interface to your code so that other source files can anticipate what is in the source, which is then compiled all together into libraries, object files, etc.
In Fortran programs (90+), you can put code into separate modules, and instead of explicitly writing a header/interface file for each one, the compiler will generate interfaces for them and put them into separate binaries (.mod files) in addition to the compiled object files. Creating libraries, object files, etc then requires you compile/link them together.
Why is there this subtle difference between how these languages compile their interfaces? Is it just a quirk that resulted from the long histories of either language?
C is far less organized than you make it sound. The use of "header" files is purely a convention; the preprocessor allows arbitrary textual inclusions, and there is no principled division of "interface" and "implementation" built into the language.
The simple fact of the matter is that linking separate translation units of a C program is not checked or "safe"; it's your responsibility that the pieces that you link actually fit together.
In early C, function declarations could be implied, and function arguments were not checked at all. So you could stick a call foo(1, 2, 3) into your code, and it would imply the declaration of a function int foo(), and the arguments would need to match the parameters that the eventual function definition would use.
The two key features in C that make header files useful are declarations and function prototypes. If you agree to always require an explicit declaration of a function before use (something compilers can warn you about), then you can provide that declaration in a "header file", and there's a better chance that the link fits. Function prototypes are an extension of the concept of declarations that automatically fix up arguments at the call site with the parameters in the function definition, and so if you choose to use all those features, you can reasonably well document your function call interface via header files. But all that is purely convention!

Why does POSIX contradict the ISO C standards [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
See
http://pubs.opengroup.org/onlinepubs/009696699/basedefs/sys/socket.h.html
(http://pubs.opengroup.org/onlinepubs/9699919799 is from Issue 7 - from 2013 and still the same!)
sockaddr_storage is meant to be cast to other structure types,
but that contradicts the ANSI and ISO C standards aliasing rules
as far as I can tell. (Objects may not be accessed through
pointers to incompatible types, with the exception that anything
can be accessed through the 3 char types and that the structure
and its first member are interchangeable.)
I know that that practice of working with sockets existed long
before C was standardised, but POSIX is supposed to conform to
ISO C and actually it contradicts the standards in its manual. (Even in the
newer versions of POSIX.)
Why did they make it like this in the first place?
Why didn't they change it?
The strict-aliasing rules in the standard constrain user code, not implementation code. Since the POSIX headers and libraries are part of the implementation, there is no actual conflict between the POSIX and the C standard.
In an open-source platform, and in particular in Linux where the C library and compiler are developed by different teams, this makes life difficult for implementors, but that is their concern, not yours. For example, the implementors could:
refrain from exposing the potential conflict between the standards (that is, disable strict-aliasing optimizations);
admit that their implementation is not POSIX compliant (and note that, for example, there are no POSIX-certified Linux distributions);
provide facilities to ensure that the potentially conflicting facilities do not actually conflict. From the point of view of the C standard, this would be an extension.
This last option is how the gcc and glibc teams are working to resolve the sockaddr issue; see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71255
As a matter of fact, I do not think there is a violation of strict aliasing rule here. Yes, you cast it to a different type when you call a function, but who said it has to be accessed through pointer of this type?
Protocol implementations know the proper type of the structure, so when they access the structure, they convert it back to the proper type. Conversion here is only used for passing pointer from one routine to another, but converted type is not used to access the data.

hard to understand this macro [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
#define __HAVE_ARCH_STRCPY
What's the meaning of __HAVE_ARCH ? I'm not a native speaker and I fail to find the meaning of it by google...(maybe this question is quite silly)
By defining the __HAVE_ARCH_XXXX pre-processor tokens, it allows other locations in the OS kernel to test if the current hardware platform supports the strcpy, memset, etc. functionality. You'll notice that on some platforms, this token is defined, and then a basic implementation of these functions are defined as inline functions along with the token, since on those platforms, the functionality is not provided by some other kernel library or kernel code module. On other platforms, the functions are defined in some other code module, and may be simply declared as extern just after the pre-processor token.
Keep in mind that the kernel itself in Linux does not have access to the standard libc library, so these functions have to be defined separately from what you would typically use in a user-land application that is linked against libc. Thus it's important to define what standard functions are present, and which ones are not, as it may vary from platform-to-platform.
"This architecture has strcpy()".

Tips/resources for structuring C code? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Does anyone have tips/resources for how to, in the best way, structure your C code projects? (Different folders etc.) And how do you know when it's good to split code into separate files? And what is an example of a good Makefile?
My project is not that big, but I wanna start to structure my code at an early stage..
Structuring code needs some experience but mostly common sense.
For splitting code, you usually go for readability: conceptually coherent functions/datatypes should go in the same file. You can take c standard library as a good example. It is better to keep your data structure definitions and function declarations in separate headers. This allows you to use the data structures as part of a compilation unit even if you have not defined all the functions.
Files that provide similar functionality should go in the same directory. It is good to avoid deep directory structure (1 level deep is best) as that complicates building the project unnecessarily.
I think Makefiles are OK for small projects, but become unwieldy for bigger ones. For really serious work (if you want to distribute your code, create an installer etc) you may want to look at cmake, scons, etc.
Have a look at the GNU coding standards: http://www.gnu.org/prep/standards/standards.html
Look at the gnu make manual for a simple example Makefile. You can also pick up any opensource project and look at the Makefile. Browsing code repositories in sourceforge.net may be useful.
Read one of the many C coding standards available on the internet and follow one that looks reasonable for your requirements. A few links:
GNU Coding Standards
C Coding Standards at IRAM (pdf)
Indian Hill C Style and Coding Standards
The following books also contain effective guidelines on writing good C code:
The C Programming Language
The Practice of Programming
The Elements of Programming Style
This is sometimes overlooked, but security is an issue in big projects. Here's some advice about how to program securely.
Here is an idiom I like:
Declare structs in a header so that their size is known by client code. Then declare init and deinit functions to the following convention:
The first parameter is a struct foo*.
The return type is a struct foo*.
If they might fail, the last parameter is either int* (simplest), enum foo_error* (if there are several ways it can fail that the calling code might care about) or GError** (if you're writing GLib-style code).
foo_init() and foo_deinit() return NULL if the first parameter is NULL. They also return the first parameter.
Why do it this way? Calling code doesn't have to allocate heap space for the structure, it can go on the stack. If you are allocating it on the heap, though, the following works nicely:
struct foo* a_foo = foo_init(malloc(sizeof(*a_foo)));
if (a_foo == NULL) {
/* Ruh-oh, allocation failure... */
}
free(foo_deinit(a_foo));
Everything works nicely even if a_foo == NULL when foo_deinit is called.

Resources