Passing a constant integer when function expects a pointer - c

What's the best/most cannonical way of passing in a constant integer value to a function that expects a pointer?
For example, the write function
write (int filedes, const void *buffer, size_t size);
Let's say I just want to write a single byte (a 1), I would think this:
write (fd, 1, 1);
but I obviously get the warning
warning: passing argument 2 of 'write' makes pointer from integer without a cast
I know I can do
int i = 1;
write (fd, &i, 1);
but is that necessary? What's the most correct way of doing this without the need of declaring/initializing a new variable?

In C89/90 you can't generally do it without declaring a new variable. The thing about pointers in C is that they always point to lvalues. Lvalue is something that has a location in memory. So, in order to supply the proper argument to your function, you need something that has a location in memory. That normally requires a definition, i.e. an object, a variable. Constants in C are not lvalues, so you can't use a constant there. Things that lie somewhat in between constants and variables are literals. C89/90 has only one kind of literal: string literal. String literals are lvalues, but not variables. So, you can use a string literal as the second argument of write.
In C99 the notion of literal was extended beyond string literals. In C99 you can also use compound literals for that purpose, which also happen to be lvalues. In your example you can call your function as
write(fd, (char[]) { 1 }, 1)
But this feature is only available in C99.

For the specific case you cite, you can do this:
write(fd, "\001", 1);
But, more generally, you must do that about which you are complaining. You must declare an object before taking its address:
SomeType i;
SomeFUnction(&i);

Yes, that's necessary. There's no other way to do this in C that is equally clear, since you can't take the address of/get a pointer to a temporary.
(And, as #rob already said, you should take the address of a char. Your example is non-portable.)
EDIT: See #AndreyT's answer and set your compiler to C99 mode.

An integer isn't a pointer. If you pass it a one, it will dereference virtual address 1 and die. You must make that variable and pass its address.

Write requires an address as is second parameter - live with it.

You can use drprintf() which prints to a file descriptor. It is similar to fprintf() which prints to a FILE *.
int dprintf(int fd, const char *format, ...);
See man 3 dprintf for details.
The functions dprintf() and vdprintf() (as found in the glibc2 library) are exact analogs of fprintf(3) and vfprintf(3), except that they output to a file descriptor fd instead of to a stdio stream.
It is POSIX.1 compliant, not universal.

write(var, new int(4))
This seems to work. Not sure how good this is as I haven't used c++ that much.
Let me know if this is a bad way to do this.

Related

I don't understand this (size_t)_length return statment

I am writing an memory allocation replacement API for a class I am in, and there is a function called my_malloc() below (with a basic skeleton already outlined from the professor) that returns something that I don't understand.
Can someone please enlighten me on why the _length argument has that underscore in the beginning, and why the return statement has (size_t) not separate from _length?
Addr my_malloc(unsigned int _length) {
/* This preliminary implementation simply hands the call over the
the C standard library!
Of course this needs to be replaced by your implementation.
*/
return malloc((size_t)_length);
}
Whoever wrote the function thought it would be a good idea to call the name _length. It doesn't have any special significance.
When you have (Typename)variablename in an expression it is called a cast. This code converts _length to the type size_t before passing it to the malloc function.
This is actually redundant because that same conversion happens implicitly when malloc is called. (Unless we are in C89 and malloc was never declared, but that should be fixed by #include <stdlib.h>, not by inserting this cast)
The underscore is just part of the variable name. I can define a variable x as well as _x or x__.
To the second question: that is an explicit type cast from int to size_t.
I recommend you read a little about type casting in C, it's important to understand.

Why do I get a warning about printf() with %s taking type void * as parameter?

I'm on programming project 4 from chapter 19 of C programming, A Modern Approach. My code works but I get this warning trying to pass a function returning a void * parameter to printf with conversion specifier %s.
format %s expects argument of type char *, but argument 2 has type void * [-Wformat=]
I can easily get rid of the warning by casting the return type of the function to char *, like
printf("%s\n", (char *) function(param));
but I just want to know why this necessary since type void * is casted to another pointer type automatically.
Compiler is very right to complain in this case.
As per your logic itself, the function returning void * could return a structure pointer casted to void *, but then, %s won't be able to print that, isn't it?
So, if you know what you're doing, you can cast the result, for this case.
Also, as others pointed out, maybe it's worthy to mention that, this warning has nothing to do with the standard specification, as in the standards, there is no restriction of the type of the arguments. (Borrowing Mr. #WhozCraig's words) This warning is basically due to an additional layer of type-checking entirely performed by compiler on it's own, enabled by -Wformat flag in gcc .
As far as the pure language is concerned (not the standard library and its expectations, the actual formal language) you can push anything you want on that argument list (including something utterly incoherent in relating to the requirements of a %s format specifier of some library routine). Of course, unless whatever you pushed ultimately is, in fact, the address of a nullchar terminated sequence of char, printf itself will trapes into undefined behavior at your behest.
The warning you're receiving is based on an additional layer of api-checking within the compiler, not some violation of the language itself. That api checking is matching format specs with types of presented arguments for frequently-used standard library apis such as printf, scanf, etc. Could the author of that warning-check been a little more forgiving and ignore void* arguments for specs expecting pointer-types? Certainly, but the point of the check-feature would dwindle pretty rapidly were that the case. Consider this:
int a = 0;
void *b = &a;
printf("%s\n", b);
If that api-check feature is going to be worth any salt at all it had better bark about that mismatched type, because as far as the language itself is concerned, there is nothing wrong with this code. And that has nothing to do with what evil I just requested it do. As far as the language is concerned, printf is simply this:
int printf(char *format ...);
And the call I setup certainly fulfills that (bad for me, and thankfully, the api-checks of my modern compiler will let me know soon enough there may be a problem).
A pointer is a variable which points to a single memory location.
The number of bytes pointed by the pointer depends on the type of the pointer. So if it is int* then it is interpreted as 4 bytes,if it is a char* it is interpreted as 1 byte.
A void* has no type. So the compiler cant dereference this pointer. So in order for the compiler to understand the memory to be dereferenced we need typecasting here.
The printf function is declared as something like this:
int printf(char *format ...);
Here ... denotes any additional arguments the caller supplied (that is, your string you wanted to print). When printf examines these additional parameters, it uses some low-level code, which has no type safety.
This code cannot determine that the parameter has type void*, and cast it to char* automatically. Instead, if the binary representation of void* and char* is the same, the parameter can be extracted from the ... part without regard to its actual type. If the representation is different, the low-level code will try to print an incorrect value (and probably crash).
Representation of void* and char* is the same for all platforms that I know of, so it's probably safe (if you trust me, that is - please don't!). However, if you compile with gcc -Wall, as some people recommend, all warnings are upgraded to errors, so you should do the casting, as the compiler indicates.

What exactly is type void and how does it work?

I've almost completed my C Primer Plus book and I'm about to hit Structures and Unions, etc... etc..., but I still don't have a full grasp of what exactly the keyword void is. What does void do? How does it work? And when should I use it?
i understand that
void function(void)
basically says that there is no return value. there are no arguments.
i know that you can use different scenarios,
int function(void); //has a return of type int -- voids args
void function(int); //voids return type -- takes type int as an arg
i also understand that
void * p = 0L;
is valid code and that it's basically a pointer-to-void with the initialized value of 0 long.
but is there any value or purpose to using it in such a way
void k = 0;
or am i just voiding the data type? and if so, is there any usefulness to voiding a data type?
because from what i've been able to infer, it's very useful in functions and pointers for working
with an undefinable data type such as
size_t fwrite(const void * restrict ptr, ...more args...);
since the first argument is not a fixed type, my book describes this as being a "catchall type for pointers" and that "Pre-ANSI C uses type char * for this argument, which requires you to typecast actual arguments to that type".
Does this mean that I can use any data type?
And if so, is this restricted to pointers and functions only?
Again... I'm not concerned with how to convert a int to void. I'm not concerned with is a pointer-to-void valid, but merely on how to effectively use this keyword. I'm concerned with "When should I use it?" and "How should I use it?".
Thanks in advance for any answers.
is there any value or purpose to using it in such a way
void k = 0;
No, that statement doesn't make any sense, and the compiler will complain about an incomplete type. Notice that whenever you see void used in a type declaration, it's followed by a * that indicates a pointer, like:
void *foo = nil;
In that case, you're telling the compiler that foo is a pointer, which is really all it needs to know in order to create foo. Without the *, you're trying to declare a variable that has no type, and that's not something that a compiler (or a human, for that matter) can work with.
since the first argument is not a fixed type, my book describes this as being a "catchall type for pointers"
The first argument is a "fixed type" -- the type is a pointer. It's true that the type that the pointer points to is unspecified, but the parameter itself is a pointer.
Does this mean that I can use any data type?
You can use a pointer to any type of data. fwrite() takes a pointer to an array of some type of object, along with the size of that type, the number of objects, and a pointer to a file, and it writes those objects to the file. fwrite() doesn't care about the type of the objects, but since it doesn't have any type information you need to explicitly pass the size and number.
There are three basic situations where the void type is used. There might be some other marginal situations, but these three are where you'll see void used, maybe 99% of the time.
It helps to understand this by keeping in mind that "void" means "there is no type here", as in "datatype".
1) Declare a function that returns no value, as opposed to a function that returns some value.
2) Declare a function that takes no parameters, as opposed to a funciton that takes one or more parameters.
3) The "pointer to void" situation.
The third case basically defines a generic pointer. A pointer to ...something, but this "something" is not important in the section of code that deals with the pointer.
For example, here's manual page for the memcpy function():
MEMCPY(3) Linux Programmer's Manual MEMCPY(3)
NAME
memcpy - copy memory area
SYNOPSIS
#include <string.h>
void *memcpy(void *dest, const void *src, size_t n);
DESCRIPTION
The memcpy() function copies n bytes from memory area src to memory
area dest. The memory areas must not overlap. Use memmove(3) if the
memory areas do overlap.
You can read the rest of the manual page yourself. memcpy() takes a couple of pointers that specify a block of memory to be copied around. memcpy() doesn't care what the pointers point to. It doesn't need to know that, so it's function prototype specifies that any pointer can be passed to it. A point to an int, a pointer to a char, or a pointer to some class instance.

Can memset() be called with a null pointer if the size is 0?

For one reason or another, I want to hand-roll a zeroing version of malloc(). To minimize algorithmic complexity, I want to write:
void * my_calloc(size_t size)
{
return memset(malloc(size), 0, size);
}
Is this well-defined when size == 0? It is fine to call malloc() with a zero size, but that allows it to return a null pointer. Will the subsequent invocation of memset be OK, or is this undefined behaviour and I need to add a conditional if (size)?
I would very much want to avoid redundant conditional checks!
Assume for the moment that malloc() doesn't fail. In reality there'll be a hand-rolled version of malloc() there, too, which will terminate on failure.
Something like this:
void * my_malloc(size_t size)
{
void * const p = malloc(size);
if (p || 0 == size) return p;
terminate();
}
Here is the glibc declaration:
extern void *memset (void *__s, int __c, size_t __n) __THROW __nonnull ((1));
The __nonnull shows that it expects the pointer to be non-null.
Here's what the C99 standard says about this:
7.1.4 "Use of library functions"
If an argument to a function has an invalid value (such as a value outside the domain of the function, or a pointer outside the address space of the program, or a null pointer, or a pointer to non-modifiable storage when the corresponding parameter is not const-qualified) or a type (after promotion) not expected by a function with variable number of arguments, the behavior is undefined.
7.21.1 "String function conventions" (remember that memset() is in string.h)
Where an argument declared as size_t n specifies the length of the array for a function, n can have the value zero on a call to that function. Unless explicitly stated otherwise in the description of a particular function in this subclause, pointer arguments on such a call shall still have valid values, as described in 7.1.4.
7.21.6.1 "The memset function"
The memset function copies the value of c (converted to an unsigned char) into each of the first n characters of the object pointed to by s.
So strictly speaking, since the standard specifies that s must point to an object, passing in a null pointer would be UB. Add the check (the cost compared to the malloc() will be vanishingly small). On the other hand, if you know the malloc() cannot fail (because you have a custom one that terminates), then obviously you don't need to perform the check before calling memset().
Edit Re:
I added this later: Assume that malloc() never fails. The question is only if size can be 0
I see. So you only want things to be secure if the pointer is null and the size is 0.
Referring to the POSIX docs
http://pubs.opengroup.org/onlinepubs/009695399/functions/memset.html
http://pubs.opengroup.org/onlinepubs/7908799/xsh/memset.html
No, it is not specified that it should be safe to call memset with a null pointer (if you called it with zero count or size... that'd be even more 'interesting', but also not specified).
Nothing about it is even mentioned in the 'informative' sections.
Note that the first link mentions
The functionality described on this reference page is aligned with the ISO C standard. Any conflict between the requirements described here and the ISO C standard is unintentional. This volume of IEEE Std 1003.1-2001 defers to the ISO C standard
Update I can confirm that the ISO C99 standard (n1256.pdf) is equally brief as the POSIX docs and the C++11 spec just refer to the ANSI C standard for memset and friends. N1256 states:
The memset function copies the value of c (converted to an unsigned char) into each of the first n characters of the object pointed to by s.
and says nothing about the situation where s is null (but note that a null pointer does not point to an object).

Why doesn't strerror return a const-qualified pointer?

I was just skimming the C99 standard, looking for something that I don't remember now, when I noticed that the pointer returned from the strerror() function (section 7.12.6.2) isn't const-qualified, even though the standard says:
The strerror function returns a pointer to the string, the contents of which are
locale-specific. The array pointed to shall not be modified by the program,
but may be overwritten by a subsequent call to the strerror function.
Is there an obvious reason for this function to return a modifiable string instead of something like:
char const * const strerror(int errnum);
or at the very least
char const * strerror(int errnum);
Same as for the type of string literals: It was already like that in C89, describing a practice dating back to before the introduction of const in the language. Changing it would make current valid program invalid.
Response about static buffer is wrong; whether the pointer type returned is const or not has nothing to do with the buffer. The return type is completely about API compatibility with historic code which does not use const, and there's no harm in it. Someone writing modern const-aware code will simply use the return value immediately or store it into a pointer-to-const variable.
This is probably so because many historical implementations use a static buffer into which they "print" the error string.

Resources