I have been attempting C recently and have been reading C source code,
however I came across this perculiar method signature with a * beside its name,
can someone explain this to me please
int *bubble_sort(int *numbers, int count, compare_cb cmp)
edit: I am referring to the * infront of bubble_sort
The asterisk has nothing to do with the function signature, it's just C's way of declaring pointers. The asterisk belongs to the type on the left, i.e. the return type for the function is int *, which is read out as "pointer to integer". The first argument has the exact same type, pointer to integer. You use this syntax everywhere in C, not just with function declarations.
The '*', used in this way, indicates that the 'bubble_sort()' function returns an address of (in other words, 'a pointer to) an integer, rather than an integer.
This concept is of pointers.
To know more about pointers see this link : http://www.tutorialspoint.com/cprogramming/c_pointers.htm
int *bubble_sort(int *numbers, int count, compare_cb cmp)
int *bubble_sort means that you are going to return the address of the integer,
and int *numbers means that you are getting the address of the variable as argument.
int a() is a function returning an int.
int * a() is a function returning a pointer to an int.
in your case the function returns a pointer to an integer.
guessing from the function name it is returning the sorted array.
an array in C is notated as a pointer to the first element:
int a[5];
int *b=a;
a and b are the same
However I guess you still have to do some more research on pointers which is not as complicated.
Perhaps this links might help: Pointer Primer
Related
I've attempted to write a program that will take an array of numbers, and produce a new array
containing the squares of the entries of the first array. Here is the function which is supposed to do this;
void square_entires(numbers, squares){
for (int i=0; i<5; ++i) {
squares[i]=numbers[i]*numbers[i];
}
}
Now I get 3 errors on the squares[i]... line saying
"Subscripted value is neither array nor pointer".
Why on earth would I want i to be an array or a pointer!? Shouldn't it simply be an index for the loop to make sense? I've seen other examples of functions which loop over array elements this way and they work fine.. just my function doesn't work properly! Can somebody please explain why this is? thanks it advance.
Your functions declaration is wrong. You must have to specify the types of the arguments in a function. It should be
void square_entires(int numbers[], int squares[])
{
Without specifying type of parameters, it will be considered int by default which is allowed in C89.
n1570: 6.5.2.2 Function calls
Each argument shall have a type such that its value may be assigned to an object with the unqualified version of the type of its corresponding parameter.
Now I get 3 errors on the squares[i]... line saying
"Subscripted value is neither array nor pointer".
Why on earth would I want i to be an array or a pointer!? Shouldn't it simply be an index for the loop to make sense?
Clearly this warning is about the variables squares and numbers which should be declared either an array or pointer. Only then subscripted value is used.
Given A[B], the "subscripted value" is A. B is the subscript.
And, what others said about the missing type specifiers and declarator bits.
When you write:
int foo(a, b)
/* <- nothing here */
{
}
you're writing an old-style function. It's how C was written before some improvements took place in the 1980's which became standardized as ANSI C. The types for a and b are declared between the function declarator and body. If they are not declared, evidently they default to int. There are two ways out. The much preferred one is to use the modern style:
int square_entries(int *numbers, int *squares) // or some other type: double?
{
}
The obsolete style, not recommended, would have looked like:
int square_entries(numbers, squares)
int *numbers;
int *squares;
{
}
[] is the Subscript operator. The expression within the brackets is referred to as a subscript. A postfix expression followed by an expression in [ ] (brackets) specifies an element of an array.
You have not specified the types for numbers, squares in
void square_entires(numbers, squares) // Defaults to type int (where actually you need type int array
This (is valid in C89) main() implicitly meant (previously) int main(void). However the default return type rule has been abandoned in C99.
I think you need this:
void square_entires(int numbers[], int squares[])
or
void square_entires(int * numbers, int * squares)
Cause array decay into pointers in functions, hence you cannot calculate the size of the array in the function - so pass the sizes as well (if required), like this:
void square_entires(int numbers[], int squares[], int sizenumbers, int sizesquares)
By definition, the expression a[b] is equivalent to the expression *((a) + (b)), and, because addition is associative, it is also equivalent to b[a].
When you pass an argument to a function, the argument should represent the type of the parameter you are going to pass. Here, when you see your passed arguments i.e. numbers and squares, it doesn't make it clear that what is the type of the data you are going to pass to your function.
Well, you are going to pass an array which contains the int data type, that is the reason why you need to declare your argument as an int array i.e. int numbers[] (where in the subscript [] represents that your argument is going to be an array and "int" represents that the array contains the data of int type".)
so, your code should be like :
void square_entires(int numbers[], int squares[])
{
I read that;
Although an array name can be used as a pointer (after decaying into pointer), it's not possible to assign it a new value. Attempting to make it point elsewhere is an error:
while (*a != 0) // a is of (int *) type
a++; //wrong
On the other hand, when passed to a function, an array name is always treated as a pointer. The function call
largest = largest_num(b, n) // b is an array of int
for the function
int find_largest(int a[], int n)
{
....
....
}
causes a pointer to the first element of b to be assigned to a.
Above two statements ( in bold ) seems to me contradictory. I am confused.
In a function declaration, an array is treated as if you'd declared a pointer, so
int find_largest(int a[], int n) {
is processed as if it were
int find_largest(int *a, int n) {
So a is a pointer, not an array, and there's no contradiction.
Since it's a pointer, you can reassign a, e.g.
a++;
is allowed.
No contradiction there - you're still working with a pointer (to int), and int a[] notation is allowed only for convenience. Quoting the comp.lang.c FAQ:
Since arrays decay immediately into pointers, an array is never
actually passed to a function. You can pretend that a function
receives an array as a parameter, and illustrate it by declaring the
corresponding parameter as an array:
void f(char a[])
Interpreted literally, this declaration would have no use, so the
compiler turns around and pretends that you'd written a pointer
declaration, since that's what the function will in fact receive:
void f(char *a)
This conversion of array-like declarators into pointers holds
only within function formal parameter declarations, nowhere else. If
the conversion bothers you, you're under no compulsion to make use of
it; many programmers have concluded that the confusion it causes
outweighs the small advantage of having the declaration ``look like''
the call or the uses within the function.
I saw this one in one of the .h files provided by my professor for a project, but I'm not too sure what this means.
int (*get_console_dev)(void);
Is it the same as
(int*) get_console_dev(void);
(a function named get_console_dev, which returns a pointer to an int?)
Thanks
It's a function pointer that can point to a function returning int and taking 0 parameters; it's not equivalent to the second line you posted.
int (*get_console_dev)(void) is a function pointer declaration. get_console_dev is a variable that can hold a reference to a function matching the specific signature.
int consoleFunction(void);
// ...
int (*get_console_dev)(void);
get_console_dev = consoleFunction;
This declaration is not the same as: (int*) get_console_dev(void);.
Check this with cdecl.
int (*get_console_dev)(void);
This is Pointer pointer function with no parameter and return type as integer.
(int*) get_console_dev(void);
This is function with no parameter and return type as pointer of type integer.
Both are completely different.
Please read up function pointers. it is a pointer to a function that takes void (as argument) and returns integer
I found this function definition
void *func(void *param) {
}
Actually, I have a certain confusion regarding this function definition. What does void * mean in the return type of the function as well as the argument. I am a beginner in C. So please don't mind. Thank you
void *func(void *param) {
int s = (int)param;
....
}
Well looking at the above program which I found. I think it should have been
int *s = (int *)param;
isn't it? I am confused
void * means it's a pointer of no specific type, think of it as a generic pointer, unlike say int * an int pointer.
You can cast it into a different type if need be (for instance if you are going to do pointer arithmetic with the pointer).
You might find this SO question of use: Concept of void pointer in C programming
It simply means that the function func takes one parameter which is a pointer (to anything) and returns a pointer (to anything). When you use a void *, you are telling the compiler "this is a pointer, but it doesn't matter at this point what it's a pointer to".
When you want to actually use the data it's pointing to, you need to cast it to a pointer to some other type. For example, if it points to an int, you can create an int * variable and dereference that:
int *int_ptr = (int *)param;
// now (*int_ptr) is the value param is pointing to
you can think of it as a raw pointer, nothing more than an address, think about it, pointers are nothing more than address right, so they should all be of equal size, either 32 or 64 bits in most modern systems but if thats the case why do we say int * or char * or so on if they are all the same size, well thats because we need of a way to interpret the type we are pointing to, int * means when we dereference go to that address and interpret the 4 bytes as an int or char * means when we dereference go to that address and get a byte, so what happens when you dereference a void * well you get warning: dereferencing ‘void *’ pointer basically we really can't and if you do its affects are compiler dependent, the same applies when we do arithmetics on it.
So why bother using them? well I personally don't and some groups dont particularly like them, fundamentally they allow you to create fairly generic subroutines, a good example would be memset which sets a block of memory to a certain byte value, its first argument is a void * so it won't complain whether giving a char * or int * due note that it works on a per byte basis, and you need to properly calculate the total size of the array.
void *func(void *param) {
}
param is a void pointer means it is a pointer of any reference type. since a void pointer has no object type,it cannot be dereferenced unless it is case.
so void *param;
int *s=(int*)param;
here since param is an pointer variable so you will have to cast it as a pointer variable.not to a int type as you did there.
e.g.
int x;
float r;
void *p=&x;
int main()
{
*(int *)p=2;
p=&r;
*(float*)p=1.1;
}
in this example p is a void pointer. now in main method I have cast the p as a int pointer and then as a float pointer so that it can reference to first a integer and then a float.
Returning a pointer of any type. It can be of any datatype.
What does this do?
int *(*pfp) ();
int *(*pfp) ();
Creates a pointer to a function that returns int*. The function pointer name ispfp.
Here's an example:
int* myFunc(void)
{
return NULL;
}
int main(int argc, char**argv)
{
int *(*pfp) (void);
pfp = myFunc;
return 0;
}
Note: Since the parameters of the function pointer is not (void) that you gave, that means that the parameter list is not specified in C. In C++ it would mean that it's a function with no parameters exactly.
Brian's explained the "what", but if you're curious as to the why, here's an excerpt from Dennis Ritchie's The Development of the C Language:
The second innovation that most clearly distinguishes C from its predecessors is this fuller type structure and especially its expression in the syntax of declarations. NB offered the basic types int and char, together with arrays of them, and pointers to them, but no further ways of composition. Generalization was required: given an object of any type, it should be possible to describe a new object that gathers several into an array, yields it from a function, or is a pointer to it.
For each object of such a composed type, there was already a way to mention the underlying object: index the array, call the function, use the indirection operator on the pointer. Analogical reasoning led to a declaration syntax for names mirroring that of the expression syntax in which the names typically appear. Thus,
int i, *pi, **ppi;
declare an integer, a pointer to an integer, a pointer to a pointer to an integer. The syntax of these declarations reflects the observation that i, *pi, and **ppi all yield an int type when used in an expression. Similarly,
int f(), *f(), (*f)();
declare a function returning an integer, a function returning a pointer to an integer, a pointer to a function returning an integer;
int *api[10], (*pai)[10];
declare an array of pointers to integers, and a pointer to an array of integers. In all these cases the declaration of a variable resembles its usage in an expression whose type is the one named at the head of the declaration.
For more info, read Steve Friedl's "Reading C type declarations" or Eric Giguere's "Reading C Declarations: A Guide for the Mystified".
pfp is a pointer to a function that takes no parameters (or indeterminate parameters in C) and returns a pointer to an int.
Using the 'clockwise-spiral' rule is an effective way to decipher complex C declarations (at least I find it effective):
http://c-faq.com/decl/spiral.anderson.html
Use http://www.cdecl.org/ for these things, if you're not sure.