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 2 years ago.
Improve this question
There are around 50 built in functions in Python. The printf and scanf functions of C is comes under stdio.h library.
Are there any functions in C that are the part of language itself?
C has a few keywords, but no built-in functions. Every function you use comes from some other library. It is possible to compile a program even without the standard library using -nostdlib flag (for gcc).
It depends on what you mean by "part of the language". There are specifications that define what the C standard library should offer, so to that extent printf(), etc., are "part of the language".
However, a C compiler won't generate the code that implements these functions -- they are expected to be provided in a library of some kind. Most C compilers will know where/what the library is, and will be configured to link it automatically. You can almost certainly tell the compiler/linker not to do this, if you don't want to use the standard library. There are sometimes good reasons to.
Although there is a specification for a standard library, the language syntax itself has little-to-no coupling to the library. In Java, for example, if you add a String and an object, the compiler will generate code to call the object's toString() method. This method has to exist, because the Java language and the Java runtime library are closely related.
There's no real equivalent to this process in C -- C compilers can generate code in complete ignorance of what functions might be available. Those functions do need to be made available before runtime, but that's really the job of the linker, rather than the compiler.
However, gcc at least does have a notion of "built-in" functions. For example, if I try to compile this:
void printf (void)
{
}
I get a warning:
test.c:1:6: warning: conflicting types for built-in function
‘printf’; expected ‘int(const char *, ...)’ [-Wbuiltin-
declaration-mismatch]
even if I use the -nostdlib switch. Even with no standard library, gcc still thinks of printf() as being "built-in" even though it doesn't generate code for it.
I guess that notion of a "built-in function" isn't entirely clear-cut.
All C standard library functions are built into the language—they are part of the C language as defined by the C standard. C implementations (notably compilers) may implement these functions either as built-in functions implemented by the compiler or as object modules linked in by the linker. The C standard largely separates the rules that says how C programs must behave from rules about how C programs must be implemented.
In the sense of how a C program must behave, there is no difference between a built-in function or a linked-in function: The function behaves the same, and there is no way to describe an observable difference between the two implementations.
Compilers generally use a mix of built-in implementations and linked-in implementations. For example, in void foo(uint32_t u) { float f; memcpy(&f, &u, sizeof f); … }, a compiler may implement the memcpy by generating an instruction to move data from an integer register to a floating-point register and not by calling any external memcpy routine. For other memcpy calls, it might generate simple instructions to move bytes and again not call an external routine. For sqrt, it might generate a square-root instruction if the target machine has an appropriate one.
More complicated functions are more often implemented by calling external functions that are linked into the program after compilation. Even with many of these, the compiler may recognize special cases and provide calls to alternative functions (printf("Hello, world.\n") may be implemented as if it were puts("Hello, world."), instructions that perform the function without a call (pow(x, 2) may be implemented as a multiplication of x by itself), or results may be computed at compile time, by code built into the compiler (sin(.3) might be evaluated at at compile time).
Related
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 1 year ago.
Improve this question
First and foremost, I'm no expert in software, and I realize this question might be as vague as it gets (it's just a curiosity), and get ready to read some barbaric guesses from my part!
The question came up from reading an article on how Linux's developers were implementing Rust into their OS (https://www.zdnet.com/article/linus-torvalds-on-where-rust-will-fit-into-linux/).
What does it even mean to implement Rust in their OS? Do they have some compiled code written in C that calls compiled code that resulted from writing in Rust? I don't see how this can efficiently be done, as you'd have different compilers probably being unable to optimize code, since, along the way, it's calling "foreign" code. I imagine the situation gets worse if you throw a language like Python or Java into the mix, which aren't precompiled. Now you would have JVM or PVM running together with compiled code, which, I imagine, would be highly impractical. One approach I can conceive, is if you see all these things as separate processes, and you'd simply have code from one language starting a process that corresponds to code from another language, but again, I imagine that wouldn't be very efficient...
Again, I realize I could've been more direct, but I'm not looking for a specific answer which addresses a problem, but rather general insight on how different languages can get used together. Thanks for understanding!
Typically when compiling a source file we have a set of options for outputs generated by the compiler, like creating a binary application from the main function, a statically linkable binary or a dynamically linkable library, or in other cases, source to source transformations.
The kernel is written in C, and to be able to compile large codebases like the kernel, we often decide to compile each, or a set of source files (the proper term would be translation unit https://en.wikipedia.org/wiki/Translation_unit_(programming)) into a statically linked library or object files. Once we've gathered all of the object files and statically (or shared) linked libraries we can link these together and produce a final binary/library.
When we're talking about integrating Rust code into the kernel, we're talking about using statically linked libraries from C in Rust and vice versa. The process of calling code produced from other compilers or languages is named Foreign Function Interface, or FFI.
There are many details and challenges with FFI including ABIs or name mangling to name a few. ABI, or application binary interface is one of the issues mentioned in your article. Unlike C, Rust does not have a stable ABI yet, meaning there's no guarantee the symbols in the static library compiled from Rust won't have different names or data layouts in the future. This means that code compiled using Rust's compiler may not be compatible with previous Rust compiler outputs which would require the C code to be updated every time there's an ABI change.
Here's how a C program is traditionally compiled:
Each source file is compiled - separately! - into an object file, which contains machine code, and placeholders for connecting all the object files together.
All the object files are joined together and the placeholders are filled in.
If you can generate some of those object files using Rust instead of C, the C compiler can't tell the difference. It's no different from a different C file!
You need to make sure the functions that cross the language barrier need to be valid functions for both languages. For example, you might not be able to pass structures as arguments, or return structures, if that's not valid in Rust (I don't actually know) - you might only be able to use primitive values, like ints and floats and pointers. If the Rust machine code expects float variables to be in certain registers, but the C machine code puts them in different registers, you might not be able to pass floats. Or you might have to put a special hint to one or the other compiler, to say "the argument goes in this register, dummy!" If the Rust compiler people didn't cooperate with the C compiler people, you are likely to run into a few of these kinds of problems, but with a bit of luck, they can all be worked around.
Since the function needs to be valid in both languages, you also need to write a C header file. You can't #include a Rust file - well you can, but it won't work - so you need to write the function declarations again in C syntax so the C compiler can understand what they are.
For languages which require VMs, it's complicated in a different way.
Usually these languages are so different from C that you can't just link together the machine code. Instead you have to use the VM's API to initialize the VM, load the code, and call the code. Something like this:
// not real code, just an illustration of how it could work
// How C starts a JVM and calls a Java method (a Java function)
void run_jvm() {
jvm_t *jvm = create_jvm();
jvm_class_t *main_class = jvm_load_class(jvm, "Main.class");
jvm_method_t *main_method = jvm_get_method(jvm, main_class, "main", NULL);
jvm_call(jvm, main_method, NULL, NULL);
delete_jvm(jvm);
}
// how Java calls a C function
void Java_HelloPrinter_printHello(jvm_t *jvm, jvm_object_t *this, jvm_args_t *args) {
printf("Hello world! My argument is %d\n", jvm_args_get_int(args, 1));
}
// how the method is declared in Java
public class HelloPrinter {
public static native void printHello(int i);
// ^^^^^^
// this means it's a C function
}
In Python or Lua, being more dynamic languages, the interpreter doesn't look for things for you. Instead, you put your functions into variables before you run any of your Python code.
// not real code, just an illustration of how it could work
// How Python calls a C function
void printHelloFunction(pvm_t *pvm, pvm_args_t *args) {
printf("Hello world! My argument is %d\n", pvm_args_get_int(args, 1));
}
// How C starts a PVM and calls a Python method
void run_python() {
pvm_t *pvm = create_pvm();
pvm_variable_t *var = pvm_create_global_variable(pvm, "printHello");
pvm_set_variable_as_c_function(pvm, var, &printHelloFunction);
pvm_load_module_from_file(pvm, "main.py");
delete_pvm(pvm);
}
These languages are not on equal footing with C, but Rust is, because Rust compiles to machine code. If you could run Java or Python code outside of a VM, they could be on equal footing. There used to be a compiler called gcj which would compile Java into machine code, but it's no longer maintained. Someone could write one, although it wouldn't run most Java programs, because a lot of those programs need to do stuff with the VM (like reflection).
Imagine a situation where you can't or don't want to use any of the libraries provided by the compiler as "standard", nor any external library. You can't use even the compiler extensions (such as gcc extensions).
What is the remaining part you get if you strip C language of all the things a lot of people use as a matter of course?
In such a way, probably a list of every callable function supported by any big C compiler (not only ANSI C) out-of-box would be satisfying as as answer as it'd at least approximately show the use-case of the language.
First I thought about sizeof() and printf() (those were already clarified in the comments - operator + stdio), so... what remains? In-line assembly seem like an extension too, so that pretty much strips even the option to use assembly with C if I'm right.
Probably in the matter of code it'd be easier to understand. Imagine a code compiled with only e.g. gcc main.c (output flag permitted) that has no #include, nor extern.
int main() {
// replace_me
return 0;
}
What can I call to actually do something else than "boring" type math and casting from type to type?
Note that switch, goto, if, loops and other constructs that do nothing and only allow repeating a piece of code aren't the thing I'm looking for (if it isn't obvious).
(Hopefully the edit clarified wtf I'm actually asking, but Matteo's answer pretty much did it.)
If you remove all libraries essentially you have something similar to a freestanding implementation of C (which still has to provide some libraries - say, string.h, but that's nothing you couldn't easily implement yourself in portable C), and that's what normally you start with when programming microcontrollers and other computers that don't have a ready-made operating system - and what operating system writers in general use when they compile their operating systems.
There you typically have two ways of doing stuff besides "raw" computation:
assembly blocks (where you can do literally anything the underlying machine can do);
memory mapped IO (you set a volatile pointer to some hardware dependent location and read/write from it; that affects hardware stuff).
That's really all you need to build anything - and after all, it all boils down to that stuff anyway, the C library of a regular hosted implementation is normally written in C itself, with some assembly used either for speed or to communicate with the operating system1 (typically the syscalls are invoked through some kind of interrupt).
Again, it's nothing you couldn't implement yourself. But the point of having a standard library is both to avoid to continuously reinvent the wheel, and to have a set of portable functions that spare you to have to rewrite everything knowing the details of each target platform.
And mainstream operating systems, in turn, are generally written in a mix or C and assembly as well.
C has no "built-in" functions as such. A compiler implementation may include "intrinsic" functions that are implemented directly by the compiler without provision of an external library, although a prototype declaration is still required for intrinsics, so you would still normally include a header file for such declarations.
C is a systems-level language with a minimal run-time and start-up requirement. Because it can directly access memory and memory mapped I/O there is very little that it cannot do (and what it cannot do is what you use assembly, in-line assembly or intrinsics for). For example, much of the library code you are wondering what you can do without is written in C. When running in an OS environment however (using C as an application-level rather then system-level language), you cannot practically use C in that manner - the OS has control over such things as I/O and memory-management and in modern systems will normally prevent unmediated access to such resources. Of course that OS itself is likely to largely written in C (and/or C++).
In a standalone of bare-metal environment with no OS, C is often used very early in the bootstrap process initialising hardware and establishing an application execution environment. In fact on ARM Cortex-M processors it is possible to boot directly into C code from reset, since the hardware loads an initial stack-pointer and start address from the vector table on start-up; this being enough to run C code that does not rely on library or static data initialisation - such initialisation can however be written in C before calling main().
Note that sizeof is not a function, it is an operator.
I don't think you really understand the situation.
You don't need a header to call a function in C. You can call with unchecked parameters - a bad idea and an obsolete feature, but still supported. And if a compiler links a library by default instead of only when you explicitly tell it to, that's only a little switch within the compiler to "link libc". Notoriously Unix compilers need to be told to link the math library, it wasn't linked by default because some very early programs didn't use floating point.
To be fair, some standard library functions like memcpy tend to be special-cased these days as they lend themselves to inlining and optimisation.
The standard library is documented and is usually available, though in effect deprecated by Microsoft for security reasons. You can write pretty much any function quite easily with only stdlib functions, what you can't do is fancy IO.
The premise: I'm writing a plug-in DLL which conforms to an industry standard interface / function signature. This will be used in at least two different software packages used internally at my company, both of which have some example skeleton code or empty shells of this particular interface. One vendor authors their example in C/C++, the other in Fortran.
Ideally I'd like to just have to write and maintain this library code in one language and not duplicate it (especially as I'm only just now getting some comfort level in various flavors of C, but haven't touched Fortran).
I've emailed off to both our vendors to see if there's anything specific their solvers need when they import this DLL, but this has made me curious at a more fundamental level. If I compile a DLL with an exposed method void foo(int bar) in both C and Fortran... by the time it's down to x86 machine instructions - does it make any difference in how that method is called by program "X"? I've gathered so far that if I were to do C++ I'd need the extern "C" bit to avoid "mangling" - there anything else I should be aware of?
It matters. The exported function must use a specific calling convention, there are several incompatible ones in common use in 32-bit code. The calling convention dictates where the function arguments are stored, in what order they are passed and how they are removed again. As well as how the function return value is passed back.
And the name of the function matters, exported function names are often decorated with extra characters. Which is what extern "C" is all about, it suppresses the name mangling that a C++ compiler uses to prevent overloaded functions from having the same exported name. So the name is one that the linker for a C compiler can recognize.
The way a C compiler makes function calls is pretty much the standard if you interop with code written in other languages. Any modern Fortran compiler will support declarations to make them compatible with a C program. And surely this is something that's already used by whatever software vendor you are working with that provides an add-on that was written in Fortran. And the other way around, as long as you provide functions that can be used by a C compiler then the Fortran programmer has a good chance at being able to call it.
Yes it has been discussed here many many times. Study answers and questions in this tag https://stackoverflow.com/questions/tagged/fortran-iso-c-binding .
The equivalent of extern "C" in fortran is bind(C). The equivalency of the datatypes is done using the intrinsic module iso_c_binding.
Also be sure to use the same calling conventions. If you do not specify anything manually, the default is usually the same for both. On Linux this is non-issue.
extern "C" is used in C++ code. So if you DLL is written in C++, you mustn't pass any C++ objects (classes).
If you stick with C types, you need to make sure the function passes parameters in a single way e.g. use C's default of _cdecl. Not sure what Fortran uses.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why do you have to link the math library in C?
When I write a program that uses functions from the math.h library, why is it that I have to explicitly link to libm even though they are part of the C standard library?
For instance, when I want to use the sin() function I need to #include <math.h> but I also need to pass -lm to GCC. But for any other library from the standard library, I don't have to do that. Why the difference?
In the old days, linkers were slow and separating the mostly unused math code from the rest made the compilation process go faster. The difference is not so great today, so you can add the -lm option to your default compiler configuration.
Note that the header <math.h> (or any other header) does not contain code. It contains information about the code, specifically how to call functions. The code itself is in a library. I mean, your program does not use the "<math.h> library", it uses the math library and uses the prototypes declared in the <math.h> header.
It's the same reason you have to explicitly link to libpthread on most implementations. When something new and scary is added to the standard library, it usually first gets implemented as a separate add-on library that overrides some of the symbols in the old standard library implementation with versions that conform to the new requirements, while also adding lots of new interfaces. I wouldn't be surprised if some historical implementations had separate versions of printf in libm for floating point printing, with a "light" version in the main libc lacking floating point. This kind of implementation is actually mentioned and encouraged for tiny systems in the ISO C rationale document, if I remember correctly.
Of course in the long-term, separating the standard library out like this leads to a lot more problems than benefits. The worst part is probably the increased load time and memory usage for dynamic-linked programs.
Actually, the reason you normally don't need to link against libm for most math functions is that these are inlined by your compiler. Your program would fail to link on a platform where this is not the case.
I apologize if this is a subjective or repeated question. It's sort of awkward to search for, so I wasn't sure what terms to include.
What I'd like to know is what the basic foundation tools/functions are in C when you don't include standard libraries like stdio and stdlib.
What could I do if there's no printf(), fopen(), etc?
Also, are those libraries technically part of the "C" language, or are they just very useful and effectively essential libraries?
The C standard has this to say (5.1.2.3/5):
The least requirements on a conforming
implementation are:
— At sequence points, volatile objects
are stable in the sense that previous
accesses are complete and subsequent
accesses have not yet occurred.
— At program termination, all data
written into files shall be identical
to the result that execution of the
program according to the abstract
semantics would have produced.
— The input and output dynamics of
interactive devices shall take place
as specified in
7.19.3.
So, without the standard library functions, the only behavior that a program is guaranteed to have, relates to the values of volatile objects, because you can't use any of the guaranteed file access or "interactive devices". "Pure C" only provides interaction via standard library functions.
Pure C isn't the whole story, though, since your hardware could have certain addresses which do certain things when read or written (whether that be a SATA or PCI bus, raw video memory, a serial port, something to go beep, or a flashing LED). So, knowing something about your hardware, you can do a whole lot writing in C without using standard library functions. Potentially, you could implement the C standard library, although this might require access to special CPU instructions as well as special memory addresses.
But in pure C, with no extensions, and the standard library functions removed, you basically can't do anything other than read the command line arguments, do some work, and return a status code from main. That's not to be sniffed at, it's still Turing complete subject to resource limits, although your only resource is automatic and static variables, no heap allocation. It's not a very rich programming environment.
The standard libraries are part of the C language specification, but in any language there does tend to be a line drawn between the language "as such", and the libraries. It's a conceptual difference, but ultimately not a very important one in principle, because the standard says they come together. Anyone doing something non-standard could just as easily remove language features as libraries. Either way, the result is not a conforming implementation of C.
Note that a "freestanding" implementation of C only has to implement a subset of standard includes not including any of the I/O, so you're in the position I described above, of relying on hardware-specific extensions to get anything interesting done. If you want to draw a distinction between the "core language" and "the libraries" based on the standard, then that might be a good place to draw the line.
What could I do if there's no printf(), fopen(), etc?
As long as you know how to interface the system you are using you can live without the standard C library. In embedded systems where you only have several kilobytes of memory, you probably don't want to use the standard library at all.
Here is a Hello World! example on Linux and Windows without using any standard C functions:
For example on Linux you can invoke the Linux system calls directly in inline assembly:
/* 64 bit linux. */
#define SYSCALL_EXIT 60
#define SYSCALL_WRITE 1
void sys_exit(int error_code)
{
asm volatile
(
"syscall"
:
: "a"(SYSCALL_EXIT), "D"(error_code)
: "rcx", "r11", "memory"
);
}
int sys_write(unsigned fd, const char *buf, unsigned count)
{
unsigned ret;
asm volatile
(
"syscall"
: "=a"(ret)
: "a"(SYSCALL_WRITE), "D"(fd), "S"(buf), "d"(count)
: "rcx", "r11", "memory"
);
return ret;
}
void _start(void)
{
const char hwText[] = "Hello world!\n";
sys_write(1, hwText, sizeof(hwText));
sys_exit(12);
}
You can look up the manual page for "syscall" which you can find how can you make system calls. On Intel x86_64 you put the system call id into RAX, and then return value will be stored in RAX. The arguments must be put into RDI, RSI, RDX, R10, R9 and R8 in this order (when the argument is used).
Once you have this you should look up how to write inline assembly in gcc.
The syscall instruction changes the RCX, R11 registers and memory so we add this to the clobber list make GCC aware of it.
The default entry point for the GNU linker is _start. Normally the standard library provides it, but without it you need to provide it.
It isn't really a function as there is no caller function to return to. So we must make another system call to exit our process.
Compile this with:
gcc -nostdlib nostd.c
And it outputs Hello world!, and exits.
On Windows the system calls are not published, instead it's hidden behind another layer of abstraction, the kernel32.dll. Which is always loaded when your program starts whether you want it or not. So you can simply include windows.h from the Windows SDK and use the Win32 API as usual:
#include <windows.h>
void _start(void)
{
const char str[] = "Hello world!\n";
HANDLE stdout = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD written;
WriteFile(stdout, str, sizeof(str), &written, NULL);
ExitProcess(12);
}
The windows.h has nothing to do with the standard C library, as you should be able to write Windows programs in any other language too.
You can compile it using the MinGW tools like this:
gcc -nostdlib C:\Windows\System32\kernel32.dll nostdlib.c
Then the compiler is smart enough to resolve the import dependencies and compile your program.
If you disassemble the program, you can see only your code is there, there is no standard library bloat in it.
So you can use C without the standard library.
What could you do? Everything!
There is no magic in C, except perhaps the preprocessor.
The hardest, perhaps is to write putchar - as that is platform dependent I/O.
It's a good undergrad exercise to create your own version of varargs and once you've got that, do your own version of vaprintf, then printf and sprintf.
I did all of then on a Macintosh in 1986 when I wasn't happy with the stdio routines that were provided with Lightspeed C - wrote my own window handler with win_putchar, win_printf, in_getchar, and win_scanf.
This whole process is called bootstrapping and it can be one of the most gratifying experiences in coding - working with a basic design that makes a fair amount of practical sense.
You're certainly not obligated to use the standard libraries if you have no need for them. Quite a few embedded systems either have no standard library support or can't use it for one reason or another. The standard even specifically talks about implementations with no library support, C99 standard 5.1.2.1 "Freestanding environment":
In a freestanding environment (in which C program execution may take place without any benefit of an operating system), the name and type of the function called at program startup are implementation-defined. Any library facilities available to a freestanding program, other than the minimal set required by clause 4, are implementation-defined.
The headers required by C99 to be available in a freestanding implemenation are <float.h>, <iso646.h>, <limits.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, and <stdint.h>. These headers define only types and macros so there's no need for a function library to support them.
Without the standard library, you're entire reliant on your own code, any non-standard libraries that might be available to you, and any operating system system calls that you might be able to interface to (which might be considered non-standard library calls). Quite possibly you'd have to have your C program call assembly routines to interface to devices and/or whatever operating system might be on the platform.
You can't do a lot, since most of the standard library functions rely on system calls; you are limited to what you can do with the built-in C keywords and operators. It also depends on the system; in some systems you may be able to manipulate bits in a way that results in some external functionality, but this is likely to be the exception rather than the rule.
C's elegance is in it's simplicity, however. Unlike Fortran, which includes much functionality as part of the language, C is quite dependent on its library. This gives it a great degree of flexibility, at the expense of being somewhat less consistent from platform to platform.
This works well, for example, in the operating system, where completely separate "libraries" are implemented, to provide similar functionality with an implementation inside the kernel itself.
Some parts of the libraries are specified as part of ANSI C; they are part of the language, I suppose, but not at its core.
None of them is part of the language keywords. However, all C distributions must include an implementation of these libraries. This ensures portability of many programs.
First of all, you could theoretically implement all these functions yourself using a combination of C and assembly, so you could theoretically do anything.
In practical terms, library functions are primarily meant to save you the work of reinventing the wheel. Some things (like string and library functions) are easier to implement. Other things (like I/O) very much depend on the operating system. Writing your own version would be possible for one O/S, but it is going to make the program less portable.
But you could write programs that do a lot of useful things (e.g., calculate PI or the meaning of life, or simulate an automata). Unless you directly used the OS for I/O, however, it would be very hard to observe what the output is.
In day to day programming, the success of a programming language typically necessitates the availability of a useful high-quality standard library and libraries for many useful tasks. These can be first-party or third-party, but they have to be there.
The std libraries are "standard" libraries, in that for a C compiler to be compliant to a standard (e.g. C99), these libraries must be "include-able." For an interesting example that might help in understanding what this means, have a look at Jessica McKellar's challenge here:
http://blog.ksplice.com/2010/03/libc-free-world/
Edit: The above link has died (thanks Oracle...)
I think this link mirrors the article: https://sudonull.com/post/178679-Hello-from-the-libc-free-world-Part-1
The CRT is part of the C language just as much as the keywords and the syntax. If you are using C, your compiler MUST provide an implementation for your target platform.
Edit:
It's the same as the STL for C++. All languages have a standard library. Maybe assembler as the exception, or some other seriously low level languages. But most medium/high levels have standard libs.
The Standard C Library is part of ANSI C89/ISO C90. I've recently been working on the library for a C compiler that previously was not ANSI-compliant.
The book The Standard C Library by P.J. Plauger was a great reference for that project. In addition to spelling out the requirements of the standard, Plauger explains the history of each .h file and the reasons behind some of the API design. He also provides a full implementation of the library, something that helped me greatly when something in the standard wasn't clear.
The standard describes the macros, types and functions for each of 15 header files (include stdio.h, stdlib.h, but also float.h, limits.h, math.h, locale.h and more).
A compiler can't claim to be ANSI C unless it includes the standard library.
Assembly language has simple commands that move values to registers of the CPU, memory, and other basic functions, as well as perform the core capabilities and calculations of the machine. C libraries are basically chunks of assembly code. You can also use assembly code in your C programs. var is an assembly code instruction. When you use 0x before a number to make it Hex, that is assembly instruction. Assembly code is the readable form of machine code, which is the visual form of the actual switch states of the circuits paths.
So while the machine code, and therefore the assembly code, is built into the machine, C languages are combined of all kinds of pre-formed combinations of code, including your own functions that might be in part assembly language and in part calling on other functions of assembly language or other C libraries. So the assembly code is the foundation of all the programming, and after that it's anyone's guess about what is what. That's why there are so many languages and so few true standards.
Yes you can do a ton of stuff without libraries.
The lifesaver is __asm__ in GCC. It is a keyword so yes you can.
Mostly because every programming language is built on Assembly, and you can make system calls directly under some OSes.