Strong Typing
Written by Nikos Vaggalis   
Thursday, 18 November 2010
Article Index
Strong Typing
Using conversion classes
Perl
Casting
Implicit conversion
Altering representation

 

Implicit conversion

Example 21

#include <stdio.h>
int main()
{
unsigned short a;
unsigned char *c;
void *p;
 a=65535;
p=&a;
c=p;

printf("dereferenced value is : %d\n", *c);
}
//dereferenced value is : 255

Here the void pointer was implicitly (without using the cast operator) converted into an unsigned char pointer, thus when dereferencing, the contents of the address will be interpreted  as unsigned char's not unsigned short's, which will result in a 1 byte shift (>>8) operation which will again result into data loss.

C acts as weakly typed language in this case; it allows converting from a void pointer to any other pointer type even if the actual type of the value has no relation to the type being converted to. Also when assigning to or from a void pointer there is an implicit cast happening.

However, when the pointer is typed  (carries type information) then we get a compiler warning:

Example 22

#include <stdio.h>
int main()
{
unsigned short a;
unsigned short *p;
unsigned char *c;
a=65535;
p=&a;
c=p;
printf("dereferenced value is %d\n", *c);
}

warning: assignment from incompatible pointer type

A much simpler example can be constructed without using void pointers and statically typing the pointer:

Example 23

#include <stdio.h>
int main()
{
 short a;
 char *p;
 a=82;
 p=&a;
}

warning: assignment from incompatible pointer type

Not having type information can result into erroneous operations and conversions that would be avoided if type checking were enforced.

Perl types its pointers

At the same time Perl, which is considered weakly typed, enforces type safety and type checking on references and disallows implicit conversions between them (and as a matter of fact it even disallows explicit conversions since there is no cast operator in Perl). So it is acting as a strongly typed language.

When you take a reference to, for example an array, then you cannot treat this reference as it is pointing to a hash:

@array=(1,2,3);
$ref=\@array;
#pointer to an array
print $$ref; 
#Use it as a pointer to scalar.

This results in a runtime exception

print %$ref; 
#Use it as a pointer to a hash.
This results in a runtime exception
print @$ref;
#Use it as a pointer to an array.

OK,at last!

or

$myref=\%a; #pointer to a hash
push @$myref,@b;
Not an ARRAY reference at 3.pl line 2.

In the examples above I tried, as in a void pointer, to interpret the contents of the address pointed at by the reference as another type, but I can't, since the referent is typed.

As a matter of fact, Perl although being untyped, always knows the type of its pointers and one can get to that information by using the ref keyword:

@a=(1,2,3);
$myref = \@a;
print ref $myref;
ARRAY

Perl knows for sure that we point to an ARRAY and to use it correctly we have to use the correct notation; so to dereference an array reference we must prepend the reference with @;

print $@myref;#123

Contrast this with the C void pointer examples.

As demonstrated, Perl uses type safe pointers. However when it comes to function pointers, Perl does guarantee type safety at a fundamental level (it is a pointer to a function and this cannot be changed), but cannot enforce either return result type safety or parameter type safety since the parameters are optional and "untyped". Recall that a scalar variable parameter can hold any scalar value; a reference to a built in type, a reference to an instance, a number (not specifically a int,short,ushort,char etc) a string, a boolean or precisely in Perl terms an integer ("IV"),a double ("NV"), a  string ("PV" for pointer value),  a reference ("RV"), and a special object ("magical").

At the same time C# does exactly employ that model of type safety when using function pointers or so called delegates.

The signature and the return result of the method must be an exact match of that of the delegate. However delegates make implicit conversions of their return value type and their parameter(s) type because they support the concept of covariance and contravariance.

It could be suggested that you should use Perl function prototypes for providing something similar but it is not foolproof and not recommended.

Type safety is important but it is not always desired. Sometimes you have to trade safety for flexibility; that is why a late bound delegate invocation also exists (dynamicinvoke) and why the new C# dynamic type was introduced and why the void pointer exists.

<ASIN:0470532874>

<ASIN:0735627045>

<ASIN:0735619573>

<ASIN:0672328917>



Last Updated ( Friday, 09 November 2012 )