Why Do I Need Asterisk Before an Array

Why do I need asterisk before an array?

The splat operator (that is, the *) turns what would otherwise be an array into a list for assignment within the hash. You have to give the [] operator an actual list to turn into the key/value pairs of a hash. See below for a link to a short description of the splat operator which actually can do this (unwind an array into a list) or the reverse (gather a list into an array).

The way you did it above, you give Hash[] an odd number of items, namely a single array. (Think of what [[:first_name, 'Shane'], [:last_name, 'Harvie']].flatten produces. It yields [:first_name, 'Shane', :last_name, 'Havie'].) As the docs you quoted say, the [] operator must have an even number of elements. Note that the following (though useless) does work:

>> Hash[[[:first_name, 'Shane'], [:last_name, 'Harvie']].flatten, 1]
=> {[:first_name, "Shane", :last_name, "Harvie"]=>1}

(It's unclear to me why you don't get the "odd number of arguments for Hash" error when using the code you have above - as you do if you try Hash[1].)

A simpler example may make it clearer. First, passing in one item, an array. The opening up the array with * to hand Hash[] a list of items:

>> Hash[['foo', 'bar', 'bizz', 'buzz']]
=> {}
>> Hash[*['foo', 'bar', 'bizz', 'buzz']]
=> {"foo"=>"bar", "bizz"=>"buzz"}

You might also find this write-up about the splat operator and the double splat operator useful.

What is the meaning of the asterisk before an array key name in print_r

The asterisk indicates an Object. And it is protected. This is the reason why you can't access them.

What does a prefixed asterisk mean

This is the spread operator and it is required to pass an existing array to a vararg function.

When we call a vararg-function, we can pass arguments one-by-one, e.g. asList(1, 2, 3), or, if we already have an array and want to pass its contents to the function, we use the spread operator (prefix the array with *):

Simplified example from the documentation:

val a = arrayOf(1, 2, 3)
val list = listOf(-1, 0, *a, 4)
println(list)

Output:

[-1, 0, 1, 2, 3, 4]

Without the spread operator, the array itself would be added as a single element, resulting in a List<Serializable> with 4 elements:

[-1, 0, [Ljava.lang.Integer;@31befd9f, 4]

What is the role of the asterisk before the parameter?

In python, an * unrolls a list.

That way you can use a list as a set of arguments.

some_args = ['first', False, 3]

do_something(*some_args)

In your case, the following is unrolling a list comprehension.

*[np.arange(x) for x in a.shape]

Why is the asterisk used before the each variable name instead of after the type?

Intuitively, I would think that int* would act like any other data type

If you want to become comfortable with C, you may need to adjust your intuition! Types are at least a little bit complicated; in fact the type system is a lot like a little programming language of its own! int is a type, but "pointer" is a meta-type. You can have pointers to anything, even pointers to pointers.

In other words, why is C designed so that each [pointer] variable needs an asterisk before it?

Because, as explained in several of the answers to that other question, the scheme is that a declaration contains a "base type" and then some "declarators". In the case of arrays, pointers, and functions, the "declarator" is a little sample of whatever thing is going to have the base type. If I say

int i;

the declarator is just i, so I'm saying that i is going to be an int. No mystery there. But if I say

int a[10];

I'm saying that one element of the array I'm declaring — that is, when I later use the array by saying something like a[i] — is going to be an int. If I say

int f();

I'm saying that calling the function is going to return an int.
Finally, if I say

int *ip;

I'm saying that when I take the contents of this pointer, using the expression *ip, then what *ip is going to be is an int.

And of course I can string these together on the same line:

int i, a[10], f(), *ip;

Now, perhaps I'm just rehashing the answers at the other question, and not explaining why things were set up this way. The reason is that it makes it possible to declare arbitrarily-complicated derived types. We can have arrays, and pointers, and functions, and arrays of arrays, and pointers to arrays, and functions returning pointers, and pointers to functions, and arrays of pointers to functions, and functions returning pointers to functions, and types even more numerous and complicated than those, and they can all be declared (in a general and open-ended way) using the same sort of concise, punctuation-rich, unwordy syntax that C is famous for

I don't think it would have been possible to design a type system that could have expressed the concept of "array of pointers to functions" on the left, leaving you to just put the variable name on the right. Or, if you could design such a system, it would have been complicated and confusing and cumbersome to use, even more complicated and confusing than C's present scheme seems to you, with its odd combination of type names on the left, and declarators — with their mixture of names, asterisks, and other punctuation — on the right.

See also Question 1.21 in the C FAQ list.


Or, perhaps I lied. I just said, "I don't think it would have been possible to design a type system that could have expressed [complicated things] on the left, leaving you to just put the variable name on the right." But, in fact, C's typedef facility lets you do precisely that, if you want to build up a complex type in stages.

For example, if you say

typedef int *pointer_to_int;

you have arranged that the identifier pointer_to_int is not an actual variable of type int *, but rather, a synonym for the type int *. Having done that, you can declare several integer pointers at once, without having to re-type those pesky asterisks:

pointer_to_int p1, p2, p3;    /* just like int *p1, *p2, *p3; */

And it works for more complicated types, too. I can say

typedef int *(*pointer_to_function_returning_pointer_to_int)();

and then do

 pointer_to_function_returning_pointer_to_int x1, x2, x3;

at which point x1, x2, and x3 are all pointers to functions returning pointers to int, just as if I'd said

int *(*x1)(), *(*x2)(), *(*x3)();

In fact, the CS50 course introduces a "handy" typedef

typedef char *string;

which makes the identifier string be an alias for the type "pointer to char", which allegedly makes it easier for beginners to declare lots of strings. Unfortunately, char * isn't really C's One True String type, so the string typedef probably causes as much confusion as it attempts to resolve. (Part of the problem is that pointers do not necessarily make good "opaque" types. If you're dealing with a pointer, you often need to know that you're dealing with a pointer, so hiding it behind a typedef doesn't help.)

Why some functions are prototyped with an asterisk?

Asterisk is a part of return type, so this function

char *strchr(const char *s, int c)

Returns char*

Also,

int *c;

is not a "pointer variable" to int, but a variable which stores int pointer (int*)

Why is the asterisk before the variable name, rather than after the type?

What does asterisk before brackets on object creation mean in C++?

new HashEntry*[TABLE_SIZE] allocates and constructs an array of TABLE_SIZE elements, where each element is a HashEntry*, i.e. a pointer to a HashEntry.

A more modern C++ version of that would be:

private:
std::vector<std::unique_ptr<HashEntry>> table;
public:
HashMap() : table(TABLE_SIZE) {}

This avoids having to define your own destructor, and is generally safer.

Pointers in C: when to use the ampersand and the asterisk?

You have pointers and values:

int* p; // variable p is pointer to integer type
int i; // integer value

You turn a pointer into a value with *:

int i2 = *p; // integer i2 is assigned with integer value that pointer p is pointing to

You turn a value into a pointer with &:

int* p2 = &i; // pointer p2 will point to the address of integer i

Edit:
In the case of arrays, they are treated very much like pointers. If you think of them as pointers, you'll be using * to get at the values inside of them as explained above, but there is also another, more common way using the [] operator:

int a[2];  // array of integers
int i = *a; // the value of the first element of a
int i2 = a[0]; // another way to get the first element

To get the second element:

int a[2]; // array
int i = *(a + 1); // the value of the second element
int i2 = a[1]; // the value of the second element

So the [] indexing operator is a special form of the * operator, and it works like this:

a[i] == *(a + i);  // these two statements are the same thing


Related Topics



Leave a reply



Submit